@taskforcehq/taskforce 0.3.305 → 0.3.307
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 +0 -2
- package/dist/Taskforce.module.css +603 -107
- package/dist/TaskforceCore.js +216 -43
- package/dist/TaskforceCore.test.js +611 -28
- 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 +46 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +561 -0
- package/dist/components/features/AgentsModule.d.ts +14 -1
- package/dist/components/features/AgentsModule.js +366 -18
- package/dist/components/features/AgentsModule.test.js +507 -8
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +7 -1
- package/dist/components/features/DocumentViewer.js +62 -4
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +51 -1
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +24 -29
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +61 -116
- package/dist/components/task/TaskForm.test.js +110 -8
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +94 -21
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +78 -14
- package/dist/components/views/PlanComparisonPage.test.js +257 -0
- package/dist/components/views/PlansPage.js +127 -36
- package/dist/components/views/PlansPage.test.js +294 -12
- package/dist/components/views/StandaloneLayout.js +529 -592
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
- package/dist/components/views/panels/PlanningDrawer.js +270 -55
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +529 -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 +26 -1
- package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
- 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 -0
- package/dist/core/AiProfileService.d.ts +46 -2
- package/dist/core/AiProfileService.js +1073 -82
- package/dist/core/AiProfileService.test.js +19 -1
- package/dist/core/AiProfiles.test.js +1249 -44
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +110 -23
- 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.js +3 -3
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +127 -6
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- package/dist/core/PlanEntitlementService.d.ts +23 -2
- package/dist/core/PlanEntitlementService.js +343 -57
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +35 -2
- package/dist/core/PlanningEntities.test.js +418 -4
- package/dist/core/SignupMonetizationSettings.test.js +199 -27
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +42 -42
- package/dist/core/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +415 -40
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +1543 -266
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/Taskforce.mcpAuth.test.js +109 -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 +117 -16
- package/dist/core/shared.d.ts +1 -1
- package/dist/core/shared.js +5 -1
- package/dist/core/types.d.ts +75 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- 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 +13 -4
- package/dist/hooks/sync/orchestratorShared.js +129 -48
- 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 +179 -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 +210 -66
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +928 -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/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
- package/dist/hooks/useSyncOrchestrator.js +409 -183
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskforce.d.ts +145 -52
- package/dist/hooks/useTaskforce.js +592 -253
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
- package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.js +13 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
- 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/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +116 -10
- package/dist/mcp/runtime.d.ts +3 -0
- package/dist/mcp/runtime.js +1099 -185
- package/dist/mcp/runtime.test.js +1491 -140
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +192 -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/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
- 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 +124 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +111 -3
- package/dist/server/routes/admin.d.ts +3 -0
- package/dist/server/routes/admin.js +459 -28
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +26 -2
- package/dist/server/routes/auth.js +1170 -71
- package/dist/server/routes/authSupport.d.ts +5 -1
- package/dist/server/routes/authSupport.js +13 -2
- package/dist/server/routes/billing.js +372 -35
- package/dist/server/routes/billing.test.js +595 -12
- package/dist/server/routes/documents.d.ts +1 -0
- package/dist/server/routes/documents.js +182 -70
- package/dist/server/routes/shared.d.ts +28 -2
- package/dist/server/routes/shared.js +69 -14
- package/dist/server/routes/sync.integration.test.js +658 -39
- package/dist/server/routes/sync.js +74 -608
- 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 +182 -0
- package/dist/server/routes/tasks.js +55 -10
- package/dist/server/routes/workspaces.js +36 -5
- package/dist/server/routes.js +147 -11
- package/dist/server/routes.test.js +2704 -183
- 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/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- 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/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- 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 +19 -11
- package/dist/sync/collaborationSyncPayload.test.js +14 -1
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +9 -9
- package/dist/sync/contentSyncState.js +248 -107
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +11 -4
- package/dist/sync/syncApplyHandlers.js +115 -42
- package/dist/sync/syncApplyHandlers.test.js +251 -4
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +46 -0
- package/dist/sync/syncResourceAdapters.js +79 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +65 -1
- package/dist/sync/syncService.test.js +96 -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.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +132 -72
- package/dist/sync/workspacePullFeed.test.js +92 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +73 -6
- package/dist/sync/workspaceSyncModel.js +342 -73
- package/dist/sync/workspaceSyncModel.test.js +559 -14
- package/dist/sync/workspaceSyncState.d.ts +17 -0
- package/dist/sync/workspaceSyncState.js +2 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +50 -2
- package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
- 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-D4rJKXzd.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
- package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.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-D5AcbO0L.js +1 -0
- package/dist/ui/assets/PlansPage-Dvqsz5zc.css +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/TaskContextUpload-uC5qx4Bv.js +1 -0
- package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
- package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
- package/dist/ui/assets/index-607WPo_X.js +4 -0
- package/dist/ui/assets/index-CYyodXsg.css +1 -0
- package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.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/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +8 -0
- package/dist/utils/assignees.js +10 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -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.js +3 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- 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 +9 -1
- package/dist/utils/taskActivity.js +290 -22
- package/dist/utils/taskActivity.test.js +141 -8
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- 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 +3 -2
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- 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-N2MnQBZk.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
- package/dist/ui/assets/index-C2-OXZV7.css +0 -1
- package/dist/ui/assets/index-DcSI5F86.js +0 -6
- 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
|
|
@@ -68,6 +71,7 @@ import { getTaskforceCloudEnvironmentConfig, resolveTaskforceCloudEnvironmentFro
|
|
|
68
71
|
import { buildCloudMcpRuntimeAuth, resolveErrorStatusCode } from './shared.js';
|
|
69
72
|
import { buildAuthBehavior, buildSiteBehavior, getRouteEmailConfig, resolvePublicAuthBaseUrl, resolveRuntimeConfigBaseUrl, } from './authSupport.js';
|
|
70
73
|
import { applyWorkspaceRepair, scanWorkspaceRepair } from '../../sync/workspaceRepair.js';
|
|
74
|
+
import { testMintAppleClientSecret } from '../auth/providers/appleClientSecret.js';
|
|
71
75
|
// === SECTION: Registration ===
|
|
72
76
|
export function registerAdminRoutes(deps) {
|
|
73
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;
|
|
@@ -75,6 +79,26 @@ export function registerAdminRoutes(deps) {
|
|
|
75
79
|
const workspaceAssetStore = typeof core.getDatabaseAdapter === 'function' && typeof core.getTenantId === 'function'
|
|
76
80
|
? new WorkspaceAssetStore(core.getDatabaseAdapter(), core.getTenantId())
|
|
77
81
|
: null;
|
|
82
|
+
const isAiProfileAvatarStorageKey = (storageKey, workspaceId) => {
|
|
83
|
+
const normalized = String(storageKey || '').replace(/\\/g, '/');
|
|
84
|
+
return normalized.startsWith(`workspaces/${workspaceId}/assets/images/ai-profiles/`)
|
|
85
|
+
&& normalized.includes('/avatar/');
|
|
86
|
+
};
|
|
87
|
+
const listReferencedAiProfileAvatarStorageKeys = (workspaceId) => {
|
|
88
|
+
const referenced = new Set();
|
|
89
|
+
const profiles = typeof core.listAiProfiles === 'function'
|
|
90
|
+
? core.listAiProfiles(workspaceId, { includeArchived: true })
|
|
91
|
+
: [];
|
|
92
|
+
for (const profile of Array.isArray(profiles) ? profiles : []) {
|
|
93
|
+
for (const value of [profile?.avatarUrl, profile?.avatarSourceUrl]) {
|
|
94
|
+
const storageKey = normalizeDocumentPathInput(value);
|
|
95
|
+
if (!storageKey || !isAiProfileAvatarStorageKey(storageKey, workspaceId))
|
|
96
|
+
continue;
|
|
97
|
+
referenced.add(storageKey);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return referenced;
|
|
101
|
+
};
|
|
78
102
|
// === SECTION: Email helpers ===
|
|
79
103
|
const resolveEffectiveVirusScanSettings = () => {
|
|
80
104
|
const settings = core.getGlobalSettings().objectStorage || {};
|
|
@@ -91,11 +115,15 @@ export function registerAdminRoutes(deps) {
|
|
|
91
115
|
};
|
|
92
116
|
// === SECTION: MCP helpers ===
|
|
93
117
|
const MCP_CONNECTION_TEST_TIMEOUT_MS = 5000;
|
|
94
|
-
const writeMcpHttpError = (res, statusCode, message) => {
|
|
118
|
+
const writeMcpHttpError = (res, statusCode, message, data) => {
|
|
95
119
|
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
96
120
|
res.end(JSON.stringify({
|
|
97
121
|
jsonrpc: '2.0',
|
|
98
|
-
error: {
|
|
122
|
+
error: {
|
|
123
|
+
code: -32000,
|
|
124
|
+
message,
|
|
125
|
+
...(data ? { data } : {}),
|
|
126
|
+
},
|
|
99
127
|
id: null,
|
|
100
128
|
}));
|
|
101
129
|
};
|
|
@@ -390,6 +418,8 @@ export function registerAdminRoutes(deps) {
|
|
|
390
418
|
authenticatedViaOAuth: oauthAuth || null,
|
|
391
419
|
userId: null,
|
|
392
420
|
...bootstrap,
|
|
421
|
+
aiProfileToken: bootstrap.aiProfileToken || oauthAuth?.aiProfileToken || null,
|
|
422
|
+
aiProfileName: bootstrap.aiProfileName || oauthAuth?.aiProfileName || null,
|
|
393
423
|
};
|
|
394
424
|
}
|
|
395
425
|
core.addMcpAuditLog({
|
|
@@ -502,6 +532,7 @@ export function registerAdminRoutes(deps) {
|
|
|
502
532
|
return;
|
|
503
533
|
}
|
|
504
534
|
const authScopes = auth.authenticatedViaToken?.scopes || auth.authenticatedViaOAuth?.scopes || [];
|
|
535
|
+
const requestId = String(req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || randomUUID();
|
|
505
536
|
const deniedToolName = findDeniedCloudMcpToolName(body, authScopes);
|
|
506
537
|
if (deniedToolName) {
|
|
507
538
|
core.addMcpAuditLog({
|
|
@@ -511,7 +542,7 @@ export function registerAdminRoutes(deps) {
|
|
|
511
542
|
tokenId: auth.authenticatedViaToken?.tokenId || auth.authenticatedViaOAuth?.grantId || null,
|
|
512
543
|
toolName: deniedToolName,
|
|
513
544
|
details: {
|
|
514
|
-
requestId
|
|
545
|
+
requestId,
|
|
515
546
|
ip: req.socket?.remoteAddress || null,
|
|
516
547
|
userAgent: requestHeader(req, 'user-agent', '') || null,
|
|
517
548
|
outcome: 'deny',
|
|
@@ -524,11 +555,13 @@ export function registerAdminRoutes(deps) {
|
|
|
524
555
|
}
|
|
525
556
|
if (!applyCloudMcpWriteRateLimit(req, res, auth, body))
|
|
526
557
|
return;
|
|
558
|
+
let runtime = null;
|
|
527
559
|
try {
|
|
528
|
-
|
|
560
|
+
runtime = createTaskforceMcpServer({
|
|
529
561
|
projectRoot: core.getPaths().projectRoot,
|
|
530
562
|
tenantId: core.getTenantId(),
|
|
531
563
|
workspaceId: auth.workspaceId,
|
|
564
|
+
core,
|
|
532
565
|
serverName: 'taskforce-cloud',
|
|
533
566
|
logStartup: false,
|
|
534
567
|
runtimeMode: 'cloud',
|
|
@@ -536,7 +569,7 @@ export function registerAdminRoutes(deps) {
|
|
|
536
569
|
req,
|
|
537
570
|
auth,
|
|
538
571
|
requestHeader,
|
|
539
|
-
requestId
|
|
572
|
+
requestId,
|
|
540
573
|
authScopes,
|
|
541
574
|
}),
|
|
542
575
|
});
|
|
@@ -553,8 +586,27 @@ export function registerAdminRoutes(deps) {
|
|
|
553
586
|
recordCloudMcpCredentialUsage(req, auth.authenticatedViaToken, auth.authenticatedViaOAuth);
|
|
554
587
|
}
|
|
555
588
|
catch (error) {
|
|
589
|
+
console.error('[Taskforce MCP] Cloud transport request failed:', {
|
|
590
|
+
requestId,
|
|
591
|
+
kind: 'tool_transport_failure',
|
|
592
|
+
message: error instanceof Error ? error.message : String(error),
|
|
593
|
+
});
|
|
556
594
|
if (!res.headersSent) {
|
|
557
|
-
writeMcpHttpError(res, 500, '
|
|
595
|
+
writeMcpHttpError(res, 500, 'MCP transport failure.', {
|
|
596
|
+
kind: 'tool_transport_failure',
|
|
597
|
+
retryable: true,
|
|
598
|
+
requestId,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
finally {
|
|
603
|
+
if (runtime) {
|
|
604
|
+
try {
|
|
605
|
+
await runtime.server.close();
|
|
606
|
+
}
|
|
607
|
+
catch (closeError) {
|
|
608
|
+
console.warn('[Taskforce MCP] Cloud transport cleanup failed:', closeError);
|
|
609
|
+
}
|
|
558
610
|
}
|
|
559
611
|
}
|
|
560
612
|
};
|
|
@@ -571,6 +623,18 @@ export function registerAdminRoutes(deps) {
|
|
|
571
623
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
572
624
|
res.end(JSON.stringify({ success: true, plans }));
|
|
573
625
|
});
|
|
626
|
+
addRoute('GET', '/api/platform/onboarding-plan-options', async (req, res) => {
|
|
627
|
+
if (!ensureCloudPlanData(req, res))
|
|
628
|
+
return;
|
|
629
|
+
if (!ensureAdminRole(req)) {
|
|
630
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
631
|
+
res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const options = core.listOnboardingPlanOptions();
|
|
635
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
636
|
+
res.end(JSON.stringify({ success: true, options }));
|
|
637
|
+
});
|
|
574
638
|
addRoute('POST', '/api/platform/plans', async (req, res) => {
|
|
575
639
|
if (!ensureCloudPlanData(req, res))
|
|
576
640
|
return;
|
|
@@ -580,10 +644,19 @@ export function registerAdminRoutes(deps) {
|
|
|
580
644
|
return;
|
|
581
645
|
}
|
|
582
646
|
const body = await parseJsonBody(req);
|
|
647
|
+
const description = body?.description === undefined || body?.description === null
|
|
648
|
+
? body?.description
|
|
649
|
+
: String(body.description);
|
|
650
|
+
if (typeof description === 'string' && description.trim().length > 240) {
|
|
651
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
652
|
+
res.end(JSON.stringify({ success: false, error: 'Plan description must be 240 characters or fewer.', code: 'PLAN_DESCRIPTION_TOO_LONG' }));
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
583
655
|
try {
|
|
584
656
|
const plan = core.upsertPlanCatalog({
|
|
585
657
|
planId: body?.planId,
|
|
586
658
|
displayName: body?.displayName,
|
|
659
|
+
description,
|
|
587
660
|
status: body?.status,
|
|
588
661
|
initialMode: body?.initialMode,
|
|
589
662
|
initialTrialDays: body?.initialTrialDays === undefined ? undefined : Number(body?.initialTrialDays),
|
|
@@ -639,6 +712,62 @@ export function registerAdminRoutes(deps) {
|
|
|
639
712
|
res.end(JSON.stringify({ success: false, error: String(error?.message || 'Unable to list feature catalog'), code: error?.code }));
|
|
640
713
|
}
|
|
641
714
|
});
|
|
715
|
+
addRoute('PATCH', '/api/platform/features/:featureKey', async (req, res, params) => {
|
|
716
|
+
if (!ensureCloudPlanData(req, res))
|
|
717
|
+
return;
|
|
718
|
+
if (!ensureAdminRole(req)) {
|
|
719
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
720
|
+
res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
const body = await parseJsonBody(req);
|
|
724
|
+
const featureKey = String(params.featureKey || '').trim();
|
|
725
|
+
const publicLabel = body?.publicLabel === undefined || body?.publicLabel === null
|
|
726
|
+
? body?.publicLabel
|
|
727
|
+
: String(body.publicLabel);
|
|
728
|
+
const publicDescription = body?.publicDescription === undefined || body?.publicDescription === null
|
|
729
|
+
? body?.publicDescription
|
|
730
|
+
: String(body.publicDescription);
|
|
731
|
+
const publicDisplayOrder = body?.publicDisplayOrder === undefined || body?.publicDisplayOrder === null || body?.publicDisplayOrder === ''
|
|
732
|
+
? null
|
|
733
|
+
: Math.max(0, Math.floor(Number(body.publicDisplayOrder)));
|
|
734
|
+
if (typeof publicLabel === 'string' && publicLabel.trim().length > 120) {
|
|
735
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
736
|
+
res.end(JSON.stringify({ success: false, error: 'Public label must be 120 characters or fewer.', code: 'PLAN_FEATURE_PUBLIC_LABEL_TOO_LONG' }));
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (typeof publicDescription === 'string' && publicDescription.trim().length > 280) {
|
|
740
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
741
|
+
res.end(JSON.stringify({ success: false, error: 'Public description must be 280 characters or fewer.', code: 'PLAN_FEATURE_PUBLIC_DESCRIPTION_TOO_LONG' }));
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
if (publicDisplayOrder !== null && !Number.isFinite(publicDisplayOrder)) {
|
|
745
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
746
|
+
res.end(JSON.stringify({ success: false, error: 'Public display order must be a non-negative number.', code: 'PLAN_FEATURE_PUBLIC_DISPLAY_ORDER_INVALID' }));
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
try {
|
|
750
|
+
const feature = core.updatePlanFeatureCatalogMarketingCopy({
|
|
751
|
+
featureKey,
|
|
752
|
+
publicLabel,
|
|
753
|
+
publicDescription,
|
|
754
|
+
publicDisplayOrder
|
|
755
|
+
});
|
|
756
|
+
auditAdminAction(req, 'platform-plan-feature-catalog-updated', {
|
|
757
|
+
featureKey,
|
|
758
|
+
publicLabel: feature.publicLabel ?? null,
|
|
759
|
+
publicDescription: feature.publicDescription ?? null,
|
|
760
|
+
publicDisplayOrder: feature.publicDisplayOrder ?? null
|
|
761
|
+
});
|
|
762
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
763
|
+
res.end(JSON.stringify({ success: true, feature }));
|
|
764
|
+
}
|
|
765
|
+
catch (error) {
|
|
766
|
+
const statusCode = resolveErrorStatusCode(error, 400);
|
|
767
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
768
|
+
res.end(JSON.stringify({ success: false, error: String(error?.message || 'Unable to update feature catalog entry'), code: error?.code }));
|
|
769
|
+
}
|
|
770
|
+
});
|
|
642
771
|
addRoute('POST', '/api/platform/plans/:planId/versions', async (req, res, params) => {
|
|
643
772
|
if (!ensureCloudPlanData(req, res))
|
|
644
773
|
return;
|
|
@@ -855,9 +984,23 @@ export function registerAdminRoutes(deps) {
|
|
|
855
984
|
res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
|
|
856
985
|
return;
|
|
857
986
|
}
|
|
858
|
-
const
|
|
987
|
+
const reqUrl = new URL(req.url || '/api/taskforce/admin/system-users', 'http://localhost');
|
|
988
|
+
const query = String(reqUrl.searchParams.get('q') || '').trim();
|
|
989
|
+
const sort = reqUrl.searchParams.get('sort') === 'oldest' ? 'oldest' : 'newest';
|
|
990
|
+
const limitRaw = Number(reqUrl.searchParams.get('limit') || '50');
|
|
991
|
+
const offsetRaw = Number(reqUrl.searchParams.get('offset') || '0');
|
|
992
|
+
const limit = Number.isFinite(limitRaw) ? Math.max(1, Math.min(200, Math.floor(limitRaw))) : 50;
|
|
993
|
+
const offset = Number.isFinite(offsetRaw) ? Math.max(0, Math.floor(offsetRaw)) : 0;
|
|
994
|
+
const total = core.countSystemUsers({ query });
|
|
995
|
+
const users = core.listSystemUsers({ query, sort, limit, offset });
|
|
859
996
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
860
|
-
res.end(JSON.stringify({
|
|
997
|
+
res.end(JSON.stringify({
|
|
998
|
+
users,
|
|
999
|
+
total,
|
|
1000
|
+
limit,
|
|
1001
|
+
offset,
|
|
1002
|
+
hasMore: offset + users.length < total
|
|
1003
|
+
}));
|
|
861
1004
|
});
|
|
862
1005
|
// GET /api/taskforce/admin/audit-logs - Read recent admin audit events
|
|
863
1006
|
addRoute('GET', '/api/taskforce/admin/audit-logs', async (req, res) => {
|
|
@@ -1136,8 +1279,10 @@ export function registerAdminRoutes(deps) {
|
|
|
1136
1279
|
}
|
|
1137
1280
|
const globalSettings = core.getGlobalSettings();
|
|
1138
1281
|
const authSettings = globalSettings.auth || {};
|
|
1139
|
-
const
|
|
1282
|
+
const siteSettings = globalSettings.site || {};
|
|
1283
|
+
const onboardingPolicy = core.getOnboardingPolicy();
|
|
1140
1284
|
const effective = buildAuthBehavior(core);
|
|
1285
|
+
const effectiveSite = buildSiteBehavior(core);
|
|
1141
1286
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1142
1287
|
res.end(JSON.stringify({
|
|
1143
1288
|
settings: {
|
|
@@ -1147,14 +1292,14 @@ export function registerAdminRoutes(deps) {
|
|
|
1147
1292
|
...(typeof authSettings.authRateLimitEnabled === 'boolean' ? { authRateLimitEnabled: authSettings.authRateLimitEnabled } : {}),
|
|
1148
1293
|
...(typeof authSettings.authRateLimitMaxRequests === 'number' ? { authRateLimitMaxRequests: authSettings.authRateLimitMaxRequests } : {}),
|
|
1149
1294
|
...(typeof authSettings.authRateLimitWindowMs === 'number' ? { authRateLimitWindowMs: authSettings.authRateLimitWindowMs } : {}),
|
|
1150
|
-
...(
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
...(typeof
|
|
1156
|
-
|
|
1157
|
-
|
|
1295
|
+
...(typeof siteSettings.showRunTaskforceLocally === 'boolean' ? { showRunTaskforceLocally: siteSettings.showRunTaskforceLocally } : {}),
|
|
1296
|
+
...(typeof siteSettings.pricingPageEnabled === 'boolean' ? { pricingPageEnabled: siteSettings.pricingPageEnabled } : {}),
|
|
1297
|
+
...(typeof siteSettings.animatedBackgroundEnabled === 'boolean' ? { animatedBackgroundEnabled: siteSettings.animatedBackgroundEnabled } : {}),
|
|
1298
|
+
...(siteSettings.siteTheme === 'light' || siteSettings.siteTheme === 'dark' ? { siteTheme: siteSettings.siteTheme } : {}),
|
|
1299
|
+
...(typeof siteSettings.pricingPageTitle === 'string' ? { pricingPageTitle: siteSettings.pricingPageTitle } : {}),
|
|
1300
|
+
...(typeof siteSettings.pricingPageDescription === 'string' ? { pricingPageDescription: siteSettings.pricingPageDescription } : {}),
|
|
1301
|
+
onboardingPolicyMode: onboardingPolicy.mode,
|
|
1302
|
+
onboardingPlanId: onboardingPolicy.planId
|
|
1158
1303
|
},
|
|
1159
1304
|
status: {
|
|
1160
1305
|
allowSelfRegistration: effective.allowSelfRegistration,
|
|
@@ -1163,8 +1308,14 @@ export function registerAdminRoutes(deps) {
|
|
|
1163
1308
|
authRateLimitEnabled: effective.authRateLimitEnabled,
|
|
1164
1309
|
authRateLimitMaxRequests: effective.authRateLimitMaxRequests,
|
|
1165
1310
|
authRateLimitWindowMs: effective.authRateLimitWindowMs,
|
|
1311
|
+
showRunTaskforceLocally: effectiveSite.showRunTaskforceLocally,
|
|
1312
|
+
pricingPageEnabled: effectiveSite.pricingPageEnabled,
|
|
1313
|
+
animatedBackgroundEnabled: effectiveSite.animatedBackgroundEnabled,
|
|
1314
|
+
siteTheme: effectiveSite.siteTheme,
|
|
1315
|
+
pricingPageTitle: effectiveSite.pricingPageTitle,
|
|
1316
|
+
pricingPageDescription: effectiveSite.pricingPageDescription,
|
|
1166
1317
|
onboardingPolicyMode: effective.onboardingPolicyMode,
|
|
1167
|
-
|
|
1318
|
+
onboardingPlanId: effective.onboardingPlanId
|
|
1168
1319
|
}
|
|
1169
1320
|
}));
|
|
1170
1321
|
});
|
|
@@ -1184,11 +1335,27 @@ export function registerAdminRoutes(deps) {
|
|
|
1184
1335
|
: {}),
|
|
1185
1336
|
...(typeof siteSettings.pricingPageEnabled === 'boolean'
|
|
1186
1337
|
? { pricingPageEnabled: siteSettings.pricingPageEnabled }
|
|
1338
|
+
: {}),
|
|
1339
|
+
...(typeof siteSettings.animatedBackgroundEnabled === 'boolean'
|
|
1340
|
+
? { animatedBackgroundEnabled: siteSettings.animatedBackgroundEnabled }
|
|
1341
|
+
: {}),
|
|
1342
|
+
...(siteSettings.siteTheme === 'light' || siteSettings.siteTheme === 'dark'
|
|
1343
|
+
? { siteTheme: siteSettings.siteTheme }
|
|
1344
|
+
: {}),
|
|
1345
|
+
...(typeof siteSettings.pricingPageTitle === 'string'
|
|
1346
|
+
? { pricingPageTitle: siteSettings.pricingPageTitle }
|
|
1347
|
+
: {}),
|
|
1348
|
+
...(typeof siteSettings.pricingPageDescription === 'string'
|
|
1349
|
+
? { pricingPageDescription: siteSettings.pricingPageDescription }
|
|
1187
1350
|
: {})
|
|
1188
1351
|
},
|
|
1189
1352
|
status: {
|
|
1190
1353
|
showRunTaskforceLocally: siteBehavior.showRunTaskforceLocally,
|
|
1191
|
-
pricingPageEnabled: siteBehavior.pricingPageEnabled
|
|
1354
|
+
pricingPageEnabled: siteBehavior.pricingPageEnabled,
|
|
1355
|
+
animatedBackgroundEnabled: siteBehavior.animatedBackgroundEnabled,
|
|
1356
|
+
siteTheme: siteBehavior.siteTheme,
|
|
1357
|
+
pricingPageTitle: siteBehavior.pricingPageTitle,
|
|
1358
|
+
pricingPageDescription: siteBehavior.pricingPageDescription
|
|
1192
1359
|
}
|
|
1193
1360
|
}));
|
|
1194
1361
|
};
|
|
@@ -1359,9 +1526,11 @@ export function registerAdminRoutes(deps) {
|
|
|
1359
1526
|
}
|
|
1360
1527
|
const reqUrl = new URL(req.url || '/api/taskforce/admin/orphaned-assets', 'http://localhost');
|
|
1361
1528
|
const workspaceId = String(reqUrl.searchParams.get('workspaceId') || requestWorkspaceId(req) || '').trim();
|
|
1529
|
+
const aiProfileAvatarStorageKeys = listReferencedAiProfileAvatarStorageKeys(workspaceId);
|
|
1362
1530
|
const assets = workspaceAssetStore.listAllByWorkspace(workspaceId, {
|
|
1363
1531
|
includeDeleted: false
|
|
1364
|
-
}).filter((asset) =>
|
|
1532
|
+
}).filter((asset) => (!aiProfileAvatarStorageKeys.has(asset.storageKey)
|
|
1533
|
+
&& workspaceAssetStore.listLinksForAsset(asset.assetId, workspaceId).every((link) => !!link.deletedAt)))
|
|
1365
1534
|
.map((asset) => ({
|
|
1366
1535
|
assetId: asset.assetId,
|
|
1367
1536
|
workspaceId: asset.workspaceId,
|
|
@@ -1440,6 +1609,11 @@ export function registerAdminRoutes(deps) {
|
|
|
1440
1609
|
res.end(JSON.stringify({ error: 'Asset not found.' }));
|
|
1441
1610
|
return;
|
|
1442
1611
|
}
|
|
1612
|
+
if (listReferencedAiProfileAvatarStorageKeys(workspaceId).has(asset.storageKey)) {
|
|
1613
|
+
res.writeHead(409, { 'Content-Type': 'application/json' });
|
|
1614
|
+
res.end(JSON.stringify({ error: 'Asset is still referenced by an AI profile avatar.' }));
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1443
1617
|
const objectStorageClient = getObjectStorageClient();
|
|
1444
1618
|
const { basePath } = core.getPaths();
|
|
1445
1619
|
try {
|
|
@@ -1471,7 +1645,8 @@ export function registerAdminRoutes(deps) {
|
|
|
1471
1645
|
workspaceAssetStore.deleteLink({
|
|
1472
1646
|
workspaceId,
|
|
1473
1647
|
assetId,
|
|
1474
|
-
|
|
1648
|
+
targetType: link.targetType,
|
|
1649
|
+
targetId: link.targetId,
|
|
1475
1650
|
role: link.role
|
|
1476
1651
|
});
|
|
1477
1652
|
}
|
|
@@ -1796,20 +1971,59 @@ export function registerAdminRoutes(deps) {
|
|
|
1796
1971
|
: body?.onboardingPolicyMode === 'require_plan_selection'
|
|
1797
1972
|
? 'require_plan_selection'
|
|
1798
1973
|
: currentOnboardingPolicy.mode;
|
|
1799
|
-
const
|
|
1800
|
-
? body.
|
|
1801
|
-
: body?.
|
|
1974
|
+
const onboardingPlanId = typeof body?.onboardingPlanId === 'string'
|
|
1975
|
+
? body.onboardingPlanId.trim().toLowerCase() || null
|
|
1976
|
+
: body?.onboardingPlanId === null
|
|
1802
1977
|
? null
|
|
1803
|
-
: currentOnboardingPolicy.
|
|
1978
|
+
: currentOnboardingPolicy.planId;
|
|
1979
|
+
const pricingPageTitle = typeof body?.pricingPageTitle === 'string'
|
|
1980
|
+
? body.pricingPageTitle.trim()
|
|
1981
|
+
: undefined;
|
|
1982
|
+
const pricingPageDescription = typeof body?.pricingPageDescription === 'string'
|
|
1983
|
+
? body.pricingPageDescription.trim()
|
|
1984
|
+
: undefined;
|
|
1985
|
+
const siteTheme = body?.siteTheme === 'light' || body?.siteTheme === 'dark'
|
|
1986
|
+
? body.siteTheme
|
|
1987
|
+
: undefined;
|
|
1988
|
+
if (pricingPageTitle !== undefined && pricingPageTitle.length > 120) {
|
|
1989
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1990
|
+
res.end(JSON.stringify({ error: 'Pricing page title must be 120 characters or fewer.', code: 'PRICING_PAGE_TITLE_TOO_LONG' }));
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1993
|
+
if (pricingPageDescription !== undefined && pricingPageDescription.length > 280) {
|
|
1994
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1995
|
+
res.end(JSON.stringify({ error: 'Pricing page description must be 280 characters or fewer.', code: 'PRICING_PAGE_DESCRIPTION_TOO_LONG' }));
|
|
1996
|
+
return;
|
|
1997
|
+
}
|
|
1804
1998
|
const validation = core.validateOnboardingPolicy({
|
|
1805
1999
|
mode: onboardingPolicyMode,
|
|
1806
|
-
|
|
2000
|
+
planId: onboardingPlanId
|
|
1807
2001
|
});
|
|
1808
2002
|
if (!validation.valid) {
|
|
1809
2003
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1810
2004
|
res.end(JSON.stringify({ error: validation.message || 'Invalid onboarding policy.', code: validation.code, details: validation.details }));
|
|
1811
2005
|
return;
|
|
1812
2006
|
}
|
|
2007
|
+
const siteSettingsUpdate = {
|
|
2008
|
+
...(typeof body?.showRunTaskforceLocally === 'boolean'
|
|
2009
|
+
? { showRunTaskforceLocally: body.showRunTaskforceLocally }
|
|
2010
|
+
: {}),
|
|
2011
|
+
...(typeof body?.pricingPageEnabled === 'boolean'
|
|
2012
|
+
? { pricingPageEnabled: body.pricingPageEnabled }
|
|
2013
|
+
: {}),
|
|
2014
|
+
...(typeof body?.animatedBackgroundEnabled === 'boolean'
|
|
2015
|
+
? { animatedBackgroundEnabled: body.animatedBackgroundEnabled }
|
|
2016
|
+
: {}),
|
|
2017
|
+
...(siteTheme !== undefined
|
|
2018
|
+
? { siteTheme }
|
|
2019
|
+
: {}),
|
|
2020
|
+
...(pricingPageTitle !== undefined
|
|
2021
|
+
? { pricingPageTitle }
|
|
2022
|
+
: {}),
|
|
2023
|
+
...(pricingPageDescription !== undefined
|
|
2024
|
+
? { pricingPageDescription }
|
|
2025
|
+
: {})
|
|
2026
|
+
};
|
|
1813
2027
|
core.updateGlobalSettings({
|
|
1814
2028
|
auth: {
|
|
1815
2029
|
...(typeof body?.allowSelfRegistration === 'boolean' ? { allowSelfRegistration: body.allowSelfRegistration } : {}),
|
|
@@ -1824,9 +2038,12 @@ export function registerAdminRoutes(deps) {
|
|
|
1824
2038
|
billing: {
|
|
1825
2039
|
onboardingPolicy: {
|
|
1826
2040
|
mode: onboardingPolicyMode,
|
|
1827
|
-
|
|
2041
|
+
planId: onboardingPlanId ?? null
|
|
1828
2042
|
}
|
|
1829
|
-
}
|
|
2043
|
+
},
|
|
2044
|
+
...(Object.keys(siteSettingsUpdate).length > 0
|
|
2045
|
+
? { site: siteSettingsUpdate }
|
|
2046
|
+
: {})
|
|
1830
2047
|
});
|
|
1831
2048
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1832
2049
|
res.end(JSON.stringify({ success: true }));
|
|
@@ -1838,6 +2055,25 @@ export function registerAdminRoutes(deps) {
|
|
|
1838
2055
|
return;
|
|
1839
2056
|
}
|
|
1840
2057
|
const body = await parseJsonBody(req);
|
|
2058
|
+
const pricingPageTitle = typeof body?.pricingPageTitle === 'string'
|
|
2059
|
+
? body.pricingPageTitle.trim()
|
|
2060
|
+
: undefined;
|
|
2061
|
+
const pricingPageDescription = typeof body?.pricingPageDescription === 'string'
|
|
2062
|
+
? body.pricingPageDescription.trim()
|
|
2063
|
+
: undefined;
|
|
2064
|
+
const siteTheme = body?.siteTheme === 'light' || body?.siteTheme === 'dark'
|
|
2065
|
+
? body.siteTheme
|
|
2066
|
+
: undefined;
|
|
2067
|
+
if (pricingPageTitle !== undefined && pricingPageTitle.length > 120) {
|
|
2068
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2069
|
+
res.end(JSON.stringify({ error: 'Pricing page title must be 120 characters or fewer.', code: 'PRICING_PAGE_TITLE_TOO_LONG' }));
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
if (pricingPageDescription !== undefined && pricingPageDescription.length > 280) {
|
|
2073
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2074
|
+
res.end(JSON.stringify({ error: 'Pricing page description must be 280 characters or fewer.', code: 'PRICING_PAGE_DESCRIPTION_TOO_LONG' }));
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
1841
2077
|
core.updateGlobalSettings({
|
|
1842
2078
|
site: {
|
|
1843
2079
|
...(typeof body?.showRunTaskforceLocally === 'boolean'
|
|
@@ -1845,6 +2081,18 @@ export function registerAdminRoutes(deps) {
|
|
|
1845
2081
|
: {}),
|
|
1846
2082
|
...(typeof body?.pricingPageEnabled === 'boolean'
|
|
1847
2083
|
? { pricingPageEnabled: body.pricingPageEnabled }
|
|
2084
|
+
: {}),
|
|
2085
|
+
...(typeof body?.animatedBackgroundEnabled === 'boolean'
|
|
2086
|
+
? { animatedBackgroundEnabled: body.animatedBackgroundEnabled }
|
|
2087
|
+
: {}),
|
|
2088
|
+
...(siteTheme !== undefined
|
|
2089
|
+
? { siteTheme }
|
|
2090
|
+
: {}),
|
|
2091
|
+
...(pricingPageTitle !== undefined
|
|
2092
|
+
? { pricingPageTitle }
|
|
2093
|
+
: {}),
|
|
2094
|
+
...(pricingPageDescription !== undefined
|
|
2095
|
+
? { pricingPageDescription }
|
|
1848
2096
|
: {})
|
|
1849
2097
|
}
|
|
1850
2098
|
});
|
|
@@ -1914,6 +2162,169 @@ export function registerAdminRoutes(deps) {
|
|
|
1914
2162
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1915
2163
|
res.end(JSON.stringify({ success: true, provider: result.provider, messageId: result.messageId || null }));
|
|
1916
2164
|
});
|
|
2165
|
+
// === SECTION: Admin auth provider settings ===
|
|
2166
|
+
// GET /api/taskforce/admin/auth-provider-settings - Read OAuth provider config (secrets masked)
|
|
2167
|
+
addRoute('GET', '/api/taskforce/admin/auth-provider-settings', async (req, res) => {
|
|
2168
|
+
if (!ensureAdminRole(req)) {
|
|
2169
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
2170
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin role required.' }));
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
if (context.authConfig?.runtimeMode !== 'cloud') {
|
|
2174
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2175
|
+
res.end(JSON.stringify({
|
|
2176
|
+
status: {
|
|
2177
|
+
google: { enabled: false, clientId: '', hasClientSecret: false, ready: false },
|
|
2178
|
+
github: { enabled: false, clientId: '', hasClientSecret: false, ready: false },
|
|
2179
|
+
apple: { enabled: false, servicesId: '', teamId: '', keyId: '', hasPrivateKeyPem: false, ready: false }
|
|
2180
|
+
}
|
|
2181
|
+
}));
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
const providers = core.getGlobalSettings().oauthProviders || {};
|
|
2185
|
+
const g = providers.google || {};
|
|
2186
|
+
const gh = providers.github || {};
|
|
2187
|
+
const ap = providers.apple || {};
|
|
2188
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2189
|
+
res.end(JSON.stringify({
|
|
2190
|
+
status: {
|
|
2191
|
+
google: {
|
|
2192
|
+
enabled: g.enabled === true,
|
|
2193
|
+
clientId: String(g.clientId || ''),
|
|
2194
|
+
hasClientSecret: typeof g.clientSecret === 'string' && g.clientSecret.trim().length > 0,
|
|
2195
|
+
ready: g.enabled === true && Boolean(g.clientId) && typeof g.clientSecret === 'string' && g.clientSecret.trim().length > 0
|
|
2196
|
+
},
|
|
2197
|
+
github: {
|
|
2198
|
+
enabled: gh.enabled === true,
|
|
2199
|
+
clientId: String(gh.clientId || ''),
|
|
2200
|
+
hasClientSecret: typeof gh.clientSecret === 'string' && gh.clientSecret.trim().length > 0,
|
|
2201
|
+
ready: gh.enabled === true && Boolean(gh.clientId) && typeof gh.clientSecret === 'string' && gh.clientSecret.trim().length > 0
|
|
2202
|
+
},
|
|
2203
|
+
apple: {
|
|
2204
|
+
enabled: ap.enabled === true,
|
|
2205
|
+
servicesId: String(ap.servicesId || ''),
|
|
2206
|
+
teamId: String(ap.teamId || ''),
|
|
2207
|
+
keyId: String(ap.keyId || ''),
|
|
2208
|
+
hasPrivateKeyPem: typeof ap.privateKeyPem === 'string' && ap.privateKeyPem.trim().length > 0,
|
|
2209
|
+
ready: ap.enabled === true && Boolean(ap.servicesId) && Boolean(ap.teamId) && Boolean(ap.keyId)
|
|
2210
|
+
&& typeof ap.privateKeyPem === 'string' && ap.privateKeyPem.trim().length > 0
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
}));
|
|
2214
|
+
});
|
|
2215
|
+
// GET /api/taskforce/admin/auth-provider-settings/health - Per-provider readiness check
|
|
2216
|
+
addRoute('GET', '/api/taskforce/admin/auth-provider-settings/health', async (req, res) => {
|
|
2217
|
+
if (!ensureAdminRole(req)) {
|
|
2218
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
2219
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin role required.' }));
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
const providers = core.getGlobalSettings().oauthProviders || {};
|
|
2223
|
+
const g = providers.google || {};
|
|
2224
|
+
const gh = providers.github || {};
|
|
2225
|
+
const ap = providers.apple || {};
|
|
2226
|
+
const googleReady = g.enabled === true && Boolean(g.clientId) && typeof g.clientSecret === 'string' && g.clientSecret.trim().length > 0;
|
|
2227
|
+
const googleReason = !g.enabled
|
|
2228
|
+
? 'Provider disabled.'
|
|
2229
|
+
: !g.clientId ? 'Missing Client ID.'
|
|
2230
|
+
: !googleReady ? 'Missing Client Secret.'
|
|
2231
|
+
: null;
|
|
2232
|
+
const githubReady = gh.enabled === true && Boolean(gh.clientId) && typeof gh.clientSecret === 'string' && gh.clientSecret.trim().length > 0;
|
|
2233
|
+
const githubReason = !gh.enabled
|
|
2234
|
+
? 'Provider disabled.'
|
|
2235
|
+
: !gh.clientId ? 'Missing Client ID.'
|
|
2236
|
+
: !githubReady ? 'Missing Client Secret.'
|
|
2237
|
+
: null;
|
|
2238
|
+
const appleBaseReady = ap.enabled === true && Boolean(ap.servicesId) && Boolean(ap.teamId) && Boolean(ap.keyId)
|
|
2239
|
+
&& typeof ap.privateKeyPem === 'string' && ap.privateKeyPem.trim().length > 0;
|
|
2240
|
+
let appleSecretMintOk;
|
|
2241
|
+
let appleReason = null;
|
|
2242
|
+
if (!ap.enabled) {
|
|
2243
|
+
appleReason = 'Provider disabled.';
|
|
2244
|
+
}
|
|
2245
|
+
else if (!ap.servicesId || !ap.teamId || !ap.keyId) {
|
|
2246
|
+
appleReason = 'Missing Services ID, Team ID, or Key ID.';
|
|
2247
|
+
}
|
|
2248
|
+
else if (!appleBaseReady) {
|
|
2249
|
+
appleReason = 'Missing private key PEM.';
|
|
2250
|
+
}
|
|
2251
|
+
else {
|
|
2252
|
+
// Attempt a test-mint to verify the key is valid
|
|
2253
|
+
const mintResult = testMintAppleClientSecret({
|
|
2254
|
+
teamId: ap.teamId,
|
|
2255
|
+
servicesId: ap.servicesId,
|
|
2256
|
+
keyId: ap.keyId,
|
|
2257
|
+
privateKeyPem: ap.privateKeyPem
|
|
2258
|
+
});
|
|
2259
|
+
appleSecretMintOk = mintResult.ok;
|
|
2260
|
+
if (!mintResult.ok) {
|
|
2261
|
+
appleReason = `Client-secret JWT mint failed: ${mintResult.error}`;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2265
|
+
res.end(JSON.stringify({
|
|
2266
|
+
success: true,
|
|
2267
|
+
health: {
|
|
2268
|
+
google: { enabled: g.enabled === true, ready: googleReady, reason: googleReason },
|
|
2269
|
+
github: { enabled: gh.enabled === true, ready: githubReady, reason: githubReason },
|
|
2270
|
+
apple: {
|
|
2271
|
+
enabled: ap.enabled === true,
|
|
2272
|
+
ready: appleBaseReady && appleSecretMintOk !== false,
|
|
2273
|
+
reason: appleReason,
|
|
2274
|
+
...(typeof appleSecretMintOk === 'boolean' ? { secretMintOk: appleSecretMintOk } : {})
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}));
|
|
2278
|
+
});
|
|
2279
|
+
// POST /api/taskforce/admin/auth-provider-settings - Save OAuth provider config (including secrets)
|
|
2280
|
+
addRoute('POST', '/api/taskforce/admin/auth-provider-settings', async (req, res) => {
|
|
2281
|
+
if (!ensureAdminRole(req)) {
|
|
2282
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
2283
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin role required.' }));
|
|
2284
|
+
return;
|
|
2285
|
+
}
|
|
2286
|
+
if (!requireCloudRuntime(res, 'Auth provider settings'))
|
|
2287
|
+
return;
|
|
2288
|
+
const body = await parseJsonBody(req);
|
|
2289
|
+
const update = {};
|
|
2290
|
+
if (body?.google && typeof body.google === 'object') {
|
|
2291
|
+
const g = body.google;
|
|
2292
|
+
update.google = {
|
|
2293
|
+
...(typeof g.enabled === 'boolean' ? { enabled: g.enabled } : {}),
|
|
2294
|
+
...(typeof g.clientId === 'string' ? { clientId: g.clientId } : {}),
|
|
2295
|
+
...(typeof g.clientSecret === 'string' ? { clientSecret: g.clientSecret } : {})
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2298
|
+
if (body?.github && typeof body.github === 'object') {
|
|
2299
|
+
const gh = body.github;
|
|
2300
|
+
update.github = {
|
|
2301
|
+
...(typeof gh.enabled === 'boolean' ? { enabled: gh.enabled } : {}),
|
|
2302
|
+
...(typeof gh.clientId === 'string' ? { clientId: gh.clientId } : {}),
|
|
2303
|
+
...(typeof gh.clientSecret === 'string' ? { clientSecret: gh.clientSecret } : {})
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
if (body?.apple && typeof body.apple === 'object') {
|
|
2307
|
+
const ap = body.apple;
|
|
2308
|
+
update.apple = {
|
|
2309
|
+
...(typeof ap.enabled === 'boolean' ? { enabled: ap.enabled } : {}),
|
|
2310
|
+
...(typeof ap.servicesId === 'string' ? { servicesId: ap.servicesId } : {}),
|
|
2311
|
+
...(typeof ap.teamId === 'string' ? { teamId: ap.teamId } : {}),
|
|
2312
|
+
...(typeof ap.keyId === 'string' ? { keyId: ap.keyId } : {}),
|
|
2313
|
+
...(typeof ap.privateKeyPem === 'string' ? { privateKeyPem: ap.privateKeyPem } : {})
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
if (Object.keys(update).length === 0) {
|
|
2317
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2318
|
+
res.end(JSON.stringify({ error: 'No provider settings provided.' }));
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
core.updateGlobalSettings({ oauthProviders: update });
|
|
2322
|
+
auditAdminAction(req, 'auth-provider-settings.update', {
|
|
2323
|
+
providers: Object.keys(update)
|
|
2324
|
+
});
|
|
2325
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2326
|
+
res.end(JSON.stringify({ success: true }));
|
|
2327
|
+
});
|
|
1917
2328
|
// === SECTION: Cloud MCP HTTP transport ===
|
|
1918
2329
|
addRoute('POST', '/mcp', async (req, res) => { await handleCloudMcpRequest(req, res); });
|
|
1919
2330
|
addRoute('POST', '/mcp/', async (req, res) => { await handleCloudMcpRequest(req, res); });
|
|
@@ -2256,6 +2667,26 @@ export function registerAdminRoutes(deps) {
|
|
|
2256
2667
|
res.end(JSON.stringify({ success: false, error: error.message, code: error?.code || 'MCP_TOKEN_REVOKE_FAILED' }));
|
|
2257
2668
|
}
|
|
2258
2669
|
});
|
|
2670
|
+
addRoute('DELETE', '/api/taskforce/settings/mcp/tokens/:id', async (req, res, params) => {
|
|
2671
|
+
if (!ensureAppAccess(req, res))
|
|
2672
|
+
return;
|
|
2673
|
+
const userId = resolveAuthenticatedUserId(req);
|
|
2674
|
+
if (!userId || userId === 'anonymous') {
|
|
2675
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
2676
|
+
res.end(JSON.stringify({ success: false, error: 'Authentication required.' }));
|
|
2677
|
+
return;
|
|
2678
|
+
}
|
|
2679
|
+
try {
|
|
2680
|
+
const deleted = core.deleteMcpAccessToken({ actorUserId: userId, workspaceId: requestWorkspaceId(req), tokenId: params.id });
|
|
2681
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2682
|
+
res.end(JSON.stringify({ success: true, deleted }));
|
|
2683
|
+
}
|
|
2684
|
+
catch (error) {
|
|
2685
|
+
const statusCode = resolveErrorStatusCode(error);
|
|
2686
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
2687
|
+
res.end(JSON.stringify({ success: false, error: error.message, code: error?.code || 'MCP_TOKEN_DELETE_FAILED' }));
|
|
2688
|
+
}
|
|
2689
|
+
});
|
|
2259
2690
|
addRoute('POST', '/api/taskforce/settings/mcp/tokens/:id/regenerate', async (req, res, params) => {
|
|
2260
2691
|
if (!ensureAppAccess(req, res))
|
|
2261
2692
|
return;
|