@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
|
@@ -56,10 +56,12 @@ import { resolveBuildInfo } from '../buildInfo.js';
|
|
|
56
56
|
import { resolveRealtimeSyncFlag } from '../../sync/realtimeFeature.js';
|
|
57
57
|
import { parseJsonBody } from './primitives.js';
|
|
58
58
|
import { resolveRequestAccess } from '../auth.js';
|
|
59
|
-
import {
|
|
59
|
+
import { getRouteTimingNow, logSlowBootstrapRoute, requestBootstrapTraceId, requestHeader, requestRuntimeMode, resolveErrorStatusCode, serializeJsonWithTiming, setServerTimingHeader } from './shared.js';
|
|
60
60
|
import { listBuiltInCustomTaxonomyLibraryPacks } from '../../shared/customTaxonomyLibrary.js';
|
|
61
61
|
import { listBuiltInTaxonomyLibraryPacks } from '../../shared/taxonomyLibrary.js';
|
|
62
62
|
import { shouldUseProvisionalTaskReferences } from '../../utils/taskReferences.js';
|
|
63
|
+
// === SECTION: Module dependency interface ===
|
|
64
|
+
const UI_STATE_MAX_JSON_BODY_BYTES = 50 * 1024 * 1024;
|
|
63
65
|
function createUiStateRequestId() {
|
|
64
66
|
return `ui-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
65
67
|
}
|
|
@@ -237,8 +239,9 @@ export function registerTaskRoutes(deps) {
|
|
|
237
239
|
const requestId = createUiStateRequestId();
|
|
238
240
|
const startedAt = Date.now();
|
|
239
241
|
attachUiStateDebugHeaders(res, requestId);
|
|
240
|
-
|
|
242
|
+
let body = {};
|
|
241
243
|
try {
|
|
244
|
+
body = await parseJsonBody(req, UI_STATE_MAX_JSON_BODY_BYTES);
|
|
242
245
|
const requestedWorkspaceId = String(body?.workspaceId || '').trim();
|
|
243
246
|
let workspaceId = requestWorkspaceId(req);
|
|
244
247
|
if (requestedWorkspaceId && requestRuntimeMode(req) === 'local') {
|
|
@@ -506,6 +509,48 @@ export function registerTaskRoutes(deps) {
|
|
|
506
509
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
507
510
|
res.end(JSON.stringify(data));
|
|
508
511
|
});
|
|
512
|
+
// GET /api/taskforce/planning/bootstrap - List planning entities plus lightweight task summaries
|
|
513
|
+
addRoute('GET', '/api/taskforce/planning/bootstrap', async (req, res) => {
|
|
514
|
+
if (!ensureAppAccess(req, res))
|
|
515
|
+
return;
|
|
516
|
+
const startedAt = getRouteTimingNow();
|
|
517
|
+
const workspaceId = requestWorkspaceId(req);
|
|
518
|
+
const traceId = requestBootstrapTraceId(req);
|
|
519
|
+
const diagnostics = {};
|
|
520
|
+
const data = core.listPlanningBootstrap(workspaceId, diagnostics);
|
|
521
|
+
const serializeStartedAt = getRouteTimingNow();
|
|
522
|
+
const serialized = serializeJsonWithTiming(data, serializeStartedAt);
|
|
523
|
+
const totalDurationMs = Math.max(0, getRouteTimingNow() - startedAt);
|
|
524
|
+
const details = diagnostics;
|
|
525
|
+
setServerTimingHeader(res, [
|
|
526
|
+
{ name: 'planning-bootstrap', durationMs: totalDurationMs },
|
|
527
|
+
{ name: 'planning-bootstrap-initiatives', durationMs: details.initiativeLoadMs ?? 0 },
|
|
528
|
+
{ name: 'planning-bootstrap-workstreams', durationMs: details.workstreamLoadMs ?? 0 },
|
|
529
|
+
{ name: 'planning-bootstrap-tasks', durationMs: details.taskSummaryQueryMs ?? 0 },
|
|
530
|
+
{ name: 'planning-bootstrap-build', durationMs: details.taskSummaryBuildMs ?? 0 },
|
|
531
|
+
{ name: 'planning-bootstrap-json', durationMs: serialized.durationMs },
|
|
532
|
+
]);
|
|
533
|
+
logSlowBootstrapRoute({
|
|
534
|
+
route: '/api/taskforce/planning/bootstrap',
|
|
535
|
+
workspaceId,
|
|
536
|
+
traceId,
|
|
537
|
+
durationMs: totalDurationMs,
|
|
538
|
+
details: {
|
|
539
|
+
initiativeCount: details.initiativeCount ?? 0,
|
|
540
|
+
workstreamCount: details.workstreamCount ?? 0,
|
|
541
|
+
workstreamLinkedTaskCount: details.workstreamLinkedTaskCount ?? 0,
|
|
542
|
+
workstreamTaskSummaryCount: details.workstreamTaskSummaryCount ?? 0,
|
|
543
|
+
responseBytes: serialized.byteLength,
|
|
544
|
+
initiativeLoadMs: details.initiativeLoadMs ?? 0,
|
|
545
|
+
workstreamLoadMs: details.workstreamLoadMs ?? 0,
|
|
546
|
+
taskSummaryQueryMs: details.taskSummaryQueryMs ?? 0,
|
|
547
|
+
taskSummaryBuildMs: details.taskSummaryBuildMs ?? 0,
|
|
548
|
+
jsonSerializeMs: serialized.durationMs,
|
|
549
|
+
},
|
|
550
|
+
});
|
|
551
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
552
|
+
res.end(serialized.body);
|
|
553
|
+
});
|
|
509
554
|
// POST /api/taskforce/initiative - Create initiative
|
|
510
555
|
addRoute('POST', '/api/taskforce/initiative', async (req, res) => {
|
|
511
556
|
if (!ensureAppAccess(req, res))
|
|
@@ -513,7 +558,7 @@ export function registerTaskRoutes(deps) {
|
|
|
513
558
|
const body = await parseJsonBody(req);
|
|
514
559
|
try {
|
|
515
560
|
const workspaceId = requestWorkspaceId(req);
|
|
516
|
-
const initiative = core.createInitiative(body || {}, workspaceId);
|
|
561
|
+
const initiative = core.createInitiative(body || {}, workspaceId, { actorRef: 'user' });
|
|
517
562
|
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
518
563
|
res.end(JSON.stringify(initiative));
|
|
519
564
|
}
|
|
@@ -545,7 +590,7 @@ export function registerTaskRoutes(deps) {
|
|
|
545
590
|
const body = await parseJsonBody(req);
|
|
546
591
|
try {
|
|
547
592
|
const workspaceId = requestWorkspaceId(req);
|
|
548
|
-
const updated = core.updateInitiative(params.id, body || {}, workspaceId);
|
|
593
|
+
const updated = core.updateInitiative(params.id, body || {}, workspaceId, { actorRef: 'user' });
|
|
549
594
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
550
595
|
res.end(JSON.stringify(updated));
|
|
551
596
|
}
|
|
@@ -561,7 +606,7 @@ export function registerTaskRoutes(deps) {
|
|
|
561
606
|
return;
|
|
562
607
|
try {
|
|
563
608
|
const workspaceId = requestWorkspaceId(req);
|
|
564
|
-
const archived = core.archiveInitiative(params.id, workspaceId);
|
|
609
|
+
const archived = core.archiveInitiative(params.id, workspaceId, { actorRef: 'user' });
|
|
565
610
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
566
611
|
res.end(JSON.stringify(archived));
|
|
567
612
|
}
|
|
@@ -577,7 +622,7 @@ export function registerTaskRoutes(deps) {
|
|
|
577
622
|
return;
|
|
578
623
|
try {
|
|
579
624
|
const workspaceId = requestWorkspaceId(req);
|
|
580
|
-
const restored = core.unarchiveInitiative(params.id, workspaceId);
|
|
625
|
+
const restored = core.unarchiveInitiative(params.id, workspaceId, { actorRef: 'user' });
|
|
581
626
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
582
627
|
res.end(JSON.stringify(restored));
|
|
583
628
|
}
|
|
@@ -604,7 +649,7 @@ export function registerTaskRoutes(deps) {
|
|
|
604
649
|
const body = await parseJsonBody(req);
|
|
605
650
|
try {
|
|
606
651
|
const workspaceId = requestWorkspaceId(req);
|
|
607
|
-
const workstream = core.createWorkstream(body || {}, workspaceId);
|
|
652
|
+
const workstream = core.createWorkstream(body || {}, workspaceId, { actorRef: 'user' });
|
|
608
653
|
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
609
654
|
res.end(JSON.stringify(workstream));
|
|
610
655
|
}
|
|
@@ -636,7 +681,7 @@ export function registerTaskRoutes(deps) {
|
|
|
636
681
|
const body = await parseJsonBody(req);
|
|
637
682
|
try {
|
|
638
683
|
const workspaceId = requestWorkspaceId(req);
|
|
639
|
-
const updated = core.updateWorkstream(params.id, body || {}, workspaceId);
|
|
684
|
+
const updated = core.updateWorkstream(params.id, body || {}, workspaceId, { actorRef: 'user' });
|
|
640
685
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
641
686
|
res.end(JSON.stringify(updated));
|
|
642
687
|
}
|
|
@@ -652,7 +697,7 @@ export function registerTaskRoutes(deps) {
|
|
|
652
697
|
return;
|
|
653
698
|
try {
|
|
654
699
|
const workspaceId = requestWorkspaceId(req);
|
|
655
|
-
const archived = core.archiveWorkstream(params.id, workspaceId);
|
|
700
|
+
const archived = core.archiveWorkstream(params.id, workspaceId, { actorRef: 'user' });
|
|
656
701
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
657
702
|
res.end(JSON.stringify(archived));
|
|
658
703
|
}
|
|
@@ -668,7 +713,7 @@ export function registerTaskRoutes(deps) {
|
|
|
668
713
|
return;
|
|
669
714
|
try {
|
|
670
715
|
const workspaceId = requestWorkspaceId(req);
|
|
671
|
-
const restored = core.unarchiveWorkstream(params.id, workspaceId);
|
|
716
|
+
const restored = core.unarchiveWorkstream(params.id, workspaceId, { actorRef: 'user' });
|
|
672
717
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
673
718
|
res.end(JSON.stringify(restored));
|
|
674
719
|
}
|
|
@@ -16,7 +16,7 @@ import * as path from 'path';
|
|
|
16
16
|
import { parseJsonBody } from './primitives.js';
|
|
17
17
|
import { resolveRequestAccess, createSessionTokenCookie, resolveSessionCookieAttributesForRequest, } from '../auth.js';
|
|
18
18
|
import { isWorkspaceSwitchingEnabledForRuntime } from '../../shared/runtimeContract.js';
|
|
19
|
-
import { resolveErrorStatusCode } from './shared.js';
|
|
19
|
+
import { getRouteTimingNow, logSlowBootstrapRoute, requestBootstrapTraceId, resolveErrorStatusCode, serializeJsonWithTiming, setServerTimingHeader } from './shared.js';
|
|
20
20
|
// === SECTION: Registration ===
|
|
21
21
|
export function registerWorkspaceRoutes(deps) {
|
|
22
22
|
const { addRoute, core, context, ensureAppAccess, auditAuthAction, getObjectStorageClient, ensureWithinDir, sanitizeStorageSegment, sanitizeTaskIdForPath, normalizeDocumentPathInput, } = deps;
|
|
@@ -94,6 +94,8 @@ export function registerWorkspaceRoutes(deps) {
|
|
|
94
94
|
// === SECTION: Workspace CRUD routes ===
|
|
95
95
|
// GET /api/taskforce/workspaces - List authenticated user's accessible workspaces
|
|
96
96
|
addRoute('GET', '/api/taskforce/workspaces', async (req, res) => {
|
|
97
|
+
const routeStartedAt = getRouteTimingNow();
|
|
98
|
+
const traceId = requestBootstrapTraceId(req);
|
|
97
99
|
const authConfig = context.authConfig;
|
|
98
100
|
if (!isWorkspaceSwitchingEnabledForRuntime(authConfig?.runtimeMode)) {
|
|
99
101
|
res.writeHead(501, { 'Content-Type': 'application/json' });
|
|
@@ -106,6 +108,7 @@ export function registerWorkspaceRoutes(deps) {
|
|
|
106
108
|
return;
|
|
107
109
|
}
|
|
108
110
|
const access = resolveRequestAccess(req, authConfig);
|
|
111
|
+
const authResolvedAt = getRouteTimingNow();
|
|
109
112
|
if (!access.authenticated || !access.userId || access.userId === 'anonymous') {
|
|
110
113
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
111
114
|
res.end(JSON.stringify({ success: false, error: 'Authentication required.' }));
|
|
@@ -113,17 +116,45 @@ export function registerWorkspaceRoutes(deps) {
|
|
|
113
116
|
}
|
|
114
117
|
if (!ensureAppAccess(req, res))
|
|
115
118
|
return;
|
|
119
|
+
const appAccessCheckedAt = getRouteTimingNow();
|
|
116
120
|
const workspaces = core.listUserWorkspaces(access.userId);
|
|
121
|
+
const workspacesLoadedAt = getRouteTimingNow();
|
|
117
122
|
const requestedCurrentWorkspaceId = String(access.workspaceId || '').trim();
|
|
118
123
|
const currentWorkspaceId = workspaces.some((workspace) => workspace.id === requestedCurrentWorkspaceId)
|
|
119
124
|
? requestedCurrentWorkspaceId
|
|
120
125
|
: (workspaces[0]?.id || 'default');
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
const currentWorkspaceResolvedAt = getRouteTimingNow();
|
|
127
|
+
const serialized = serializeJsonWithTiming({
|
|
123
128
|
success: true,
|
|
124
129
|
workspaces,
|
|
125
130
|
currentWorkspaceId: currentWorkspaceId || access.workspaceId
|
|
126
|
-
})
|
|
131
|
+
}, currentWorkspaceResolvedAt);
|
|
132
|
+
const totalDurationMs = getRouteTimingNow() - routeStartedAt;
|
|
133
|
+
setServerTimingHeader(res, [
|
|
134
|
+
{ name: 'workspaces', durationMs: totalDurationMs },
|
|
135
|
+
{ name: 'workspaces-auth', durationMs: authResolvedAt - routeStartedAt },
|
|
136
|
+
{ name: 'workspaces-app-access', durationMs: appAccessCheckedAt - authResolvedAt },
|
|
137
|
+
{ name: 'workspaces-list', durationMs: workspacesLoadedAt - appAccessCheckedAt },
|
|
138
|
+
{ name: 'workspaces-current', durationMs: currentWorkspaceResolvedAt - workspacesLoadedAt },
|
|
139
|
+
{ name: 'workspaces-json', durationMs: serialized.durationMs },
|
|
140
|
+
]);
|
|
141
|
+
logSlowBootstrapRoute({
|
|
142
|
+
route: '/api/taskforce/workspaces',
|
|
143
|
+
workspaceId: currentWorkspaceId || access.workspaceId || 'default',
|
|
144
|
+
traceId,
|
|
145
|
+
durationMs: totalDurationMs,
|
|
146
|
+
details: {
|
|
147
|
+
workspaceCount: workspaces.length,
|
|
148
|
+
payloadBytes: serialized.byteLength,
|
|
149
|
+
authMs: authResolvedAt - routeStartedAt,
|
|
150
|
+
appAccessMs: appAccessCheckedAt - authResolvedAt,
|
|
151
|
+
listWorkspacesMs: workspacesLoadedAt - appAccessCheckedAt,
|
|
152
|
+
currentWorkspaceMs: currentWorkspaceResolvedAt - workspacesLoadedAt,
|
|
153
|
+
serializeMs: serialized.durationMs,
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
157
|
+
res.end(serialized.body);
|
|
127
158
|
});
|
|
128
159
|
// POST /api/taskforce/workspaces - Create workspace for current authenticated user
|
|
129
160
|
addRoute('POST', '/api/taskforce/workspaces', async (req, res) => {
|
|
@@ -281,7 +312,7 @@ export function registerWorkspaceRoutes(deps) {
|
|
|
281
312
|
return;
|
|
282
313
|
}
|
|
283
314
|
const resolved = core.resolveUserAccess(access.userId, workspaceId, access.role);
|
|
284
|
-
if (!resolved || resolved.
|
|
315
|
+
if (!resolved || resolved.disabled) {
|
|
285
316
|
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
286
317
|
res.end(JSON.stringify({ success: false, error: 'Workspace access is not active for this user.' }));
|
|
287
318
|
return;
|
package/dist/server/routes.js
CHANGED
|
@@ -36,12 +36,33 @@ import { registerDocumentReviewRoutes } from './routes/documentReviews.js';
|
|
|
36
36
|
import { registerAnnotatedAttachmentRoutes } from './routes/annotatedAttachments.js';
|
|
37
37
|
import { escapeHtml, parseJsonBody } from './routes/primitives.js';
|
|
38
38
|
import { getRouteEmailConfig, resolvePublicAuthBaseUrl, resolveRuntimeConfigBaseUrl } from './routes/authSupport.js';
|
|
39
|
-
import { buildCloudMcpRuntimeAuth, requestHeader, requestRole, requestRuntimeMode, requestUserId, makeAuditAdminAction, makeAuditAuthAction, makeEnsureAdminRole, makeEnsureAppAccess, makeEnsureAuthenticatedUser, makeEnsureCloudPlanData, makeRequestWorkspaceId, makeRequireCloudRuntime, makeResolveAdminRequestActor, makeResolveAuthenticatedUserId, makeResolveAuthenticatedMutationUserId,
|
|
39
|
+
import { buildCloudMcpRuntimeAuth, requestHeader, requestRole, requestRuntimeMode, requestUserId, makeAuditAdminAction, makeAuditAuthAction, makeEnsureAdminRole, makeEnsureAppAccess, makeEnsureAuthenticatedUser, makeEnsureCloudPlanData, makeRequestWorkspaceId, makeRequireCloudRuntime, makeResolveAdminRequestActor, makeResolveAuthenticatedUserId, makeResolveAuthenticatedMutationUserId, } from './routes/shared.js';
|
|
40
40
|
import { resolveDeploymentConfig } from '../config/deployment.js';
|
|
41
41
|
import { getTaskforceCloudEnvironmentConfig, resolveTaskforceCloudEnvironmentFromBaseUrl } from '../config/cloudEnvironment.js';
|
|
42
42
|
import { getCanonicalDocumentName } from '../utils/documentNames.js';
|
|
43
43
|
import { MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS } from '../mcp/toolRegistry.js';
|
|
44
44
|
export { parseJsonBody } from './routes/primitives.js';
|
|
45
|
+
function pathMatchesRouteAuthExclusion(pathname, excludedPaths) {
|
|
46
|
+
if (!Array.isArray(excludedPaths))
|
|
47
|
+
return false;
|
|
48
|
+
return excludedPaths.some((path) => pathname === path || pathname.startsWith(`${path}/`));
|
|
49
|
+
}
|
|
50
|
+
function shouldRequireAuthenticatedCloudApiRoute(pathname, context) {
|
|
51
|
+
const authConfig = context.authConfig;
|
|
52
|
+
if (!authConfig?.enabled)
|
|
53
|
+
return false;
|
|
54
|
+
if (!pathname.startsWith('/api/taskforce/'))
|
|
55
|
+
return false;
|
|
56
|
+
if (pathname.startsWith('/api/taskforce/sync/'))
|
|
57
|
+
return false;
|
|
58
|
+
if (pathMatchesRouteAuthExclusion(pathname, authConfig.excludedPaths))
|
|
59
|
+
return false;
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
function writeRouteAuthenticationRequired(res) {
|
|
63
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
64
|
+
res.end(JSON.stringify({ error: 'Authentication required.' }));
|
|
65
|
+
}
|
|
45
66
|
const DEFAULT_DOCUMENT_RETENTION_DAYS = 7;
|
|
46
67
|
const STORAGE_INTEGRITY_HISTORY_LIMIT = 50;
|
|
47
68
|
const MCP_TOKEN_SCOPE_VALUES = new Set(['tasks:read', 'tasks:write', 'workspace:read']);
|
|
@@ -90,13 +111,14 @@ function resolveErrorStatusCode(error, fallback = 400) {
|
|
|
90
111
|
}
|
|
91
112
|
return fallback;
|
|
92
113
|
}
|
|
93
|
-
function writeMcpHttpError(res, statusCode, message) {
|
|
114
|
+
function writeMcpHttpError(res, statusCode, message, data) {
|
|
94
115
|
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
95
116
|
res.end(JSON.stringify({
|
|
96
117
|
jsonrpc: '2.0',
|
|
97
118
|
error: {
|
|
98
119
|
code: -32000,
|
|
99
120
|
message,
|
|
121
|
+
...(data ? { data } : {}),
|
|
100
122
|
},
|
|
101
123
|
id: null,
|
|
102
124
|
}));
|
|
@@ -175,8 +197,24 @@ export function createRoutes(core, context = {}) {
|
|
|
175
197
|
const routes = [];
|
|
176
198
|
const uiStateCache = new Map();
|
|
177
199
|
const addRoute = (method, path, handler) => {
|
|
200
|
+
const wrappedHandler = async (req, res, params) => {
|
|
201
|
+
const runtimeHeader = requestHeader(req, 'x-taskforce-runtime-mode', '').trim().toLowerCase();
|
|
202
|
+
const runtimeMode = runtimeHeader === 'cloud'
|
|
203
|
+
? 'cloud'
|
|
204
|
+
: runtimeHeader === 'local'
|
|
205
|
+
? 'local'
|
|
206
|
+
: (context.authConfig?.runtimeMode || requestRuntimeMode(req));
|
|
207
|
+
if (runtimeMode === 'cloud' && shouldRequireAuthenticatedCloudApiRoute(path, context)) {
|
|
208
|
+
const access = resolveRequestAccess(req, context.authConfig);
|
|
209
|
+
if (!access.authenticated || !access.userId || access.userId === 'anonymous') {
|
|
210
|
+
writeRouteAuthenticationRequired(res);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
await handler(req, res, params);
|
|
215
|
+
};
|
|
178
216
|
const { pattern, keys } = createRoutePattern(`${method}:${path}`);
|
|
179
|
-
routes.push({ pattern, keys, handler });
|
|
217
|
+
routes.push({ pattern, keys, handler: wrappedHandler });
|
|
180
218
|
};
|
|
181
219
|
const buildUiStateCacheKey = (workspaceId, userId, stateKey) => `${workspaceId}::${userId}::${stateKey}`;
|
|
182
220
|
const readCachedUiState = (workspaceId, userId, stateKey) => {
|
|
@@ -485,7 +523,10 @@ export function createRoutes(core, context = {}) {
|
|
|
485
523
|
const primaryLink = canonicalAsset?.assetId
|
|
486
524
|
? workspaceAssetStore?.listLinksForAsset(canonicalAsset.assetId, inferWorkspaceIdFromStoragePath(normalizedStorageKey)).find((entry) => !entry.deletedAt && (!opts?.taskId || entry.taskId === opts.taskId))
|
|
487
525
|
: null;
|
|
526
|
+
const isExplicitTaskAttachment = typeof opts?.taskId === 'string' && opts.taskId.trim().length > 0;
|
|
488
527
|
const timestamp = String(opts?.timestamp
|
|
528
|
+
|| primaryLink?.updatedAt
|
|
529
|
+
|| (isExplicitTaskAttachment ? new Date().toISOString() : null)
|
|
489
530
|
|| canonicalAsset?.updatedAt
|
|
490
531
|
|| canonicalAsset?.createdAt
|
|
491
532
|
|| new Date().toISOString()).trim() || new Date().toISOString();
|
|
@@ -530,6 +571,45 @@ export function createRoutes(core, context = {}) {
|
|
|
530
571
|
taskId
|
|
531
572
|
};
|
|
532
573
|
};
|
|
574
|
+
const taskHasAttachmentForAsset = (task, asset) => {
|
|
575
|
+
if (!task || !Array.isArray(task.attachments))
|
|
576
|
+
return false;
|
|
577
|
+
const canonicalDocumentPath = `/api/taskforce/documents/${encodeURIComponent(asset.assetId)}/content`;
|
|
578
|
+
const contextPath = `/api/taskforce/context/${encodeURIComponent(asset.storageKey)}`;
|
|
579
|
+
return task.attachments.some((attachment) => {
|
|
580
|
+
if (typeof attachment === 'string') {
|
|
581
|
+
return attachment === canonicalDocumentPath
|
|
582
|
+
|| attachment === contextPath
|
|
583
|
+
|| attachment === asset.storageKey;
|
|
584
|
+
}
|
|
585
|
+
if (!attachment || typeof attachment !== 'object')
|
|
586
|
+
return false;
|
|
587
|
+
return attachment.assetId === asset.assetId
|
|
588
|
+
|| attachment.fsPath === asset.storageKey
|
|
589
|
+
|| attachment.path === canonicalDocumentPath
|
|
590
|
+
|| attachment.path === contextPath;
|
|
591
|
+
});
|
|
592
|
+
};
|
|
593
|
+
const recordTaskAttachmentActivity = (input) => {
|
|
594
|
+
const afterTask = core.getTask(input.taskId, input.workspaceId);
|
|
595
|
+
if (!taskHasAttachmentForAsset(afterTask, input.asset))
|
|
596
|
+
return;
|
|
597
|
+
core.recordTaskEvent({
|
|
598
|
+
taskId: input.taskId,
|
|
599
|
+
workspaceId: input.workspaceId,
|
|
600
|
+
action: 'task-attachments-changed',
|
|
601
|
+
actor: 'user',
|
|
602
|
+
createdAt: input.createdAt || new Date().toISOString(),
|
|
603
|
+
details: {
|
|
604
|
+
changes: {
|
|
605
|
+
attachments: {
|
|
606
|
+
from: input.beforeTask.attachments || [],
|
|
607
|
+
to: afterTask?.attachments || [],
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
};
|
|
533
613
|
const sanitizeDownloadFilename = (nameRaw, fallback = 'download') => {
|
|
534
614
|
const normalized = String(nameRaw || '').trim()
|
|
535
615
|
.replace(/[\\/:*?"<>|]/g, '-')
|
|
@@ -623,6 +703,8 @@ export function createRoutes(core, context = {}) {
|
|
|
623
703
|
purgeAfter: null
|
|
624
704
|
});
|
|
625
705
|
const taskId = String(params.taskId || inferTaskIdFromStoragePath(params.relativeToStorage) || '').trim();
|
|
706
|
+
const taskBeforeLink = taskId ? core.getTask(taskId, workspaceId) : null;
|
|
707
|
+
const wasAttachedBefore = taskHasAttachmentForAsset(taskBeforeLink, asset);
|
|
626
708
|
if (taskId) {
|
|
627
709
|
workspaceAssetStore.upsertLink({
|
|
628
710
|
workspaceId,
|
|
@@ -632,6 +714,15 @@ export function createRoutes(core, context = {}) {
|
|
|
632
714
|
displayName: null,
|
|
633
715
|
deletedAt: null
|
|
634
716
|
});
|
|
717
|
+
if (taskBeforeLink && !wasAttachedBefore) {
|
|
718
|
+
recordTaskAttachmentActivity({
|
|
719
|
+
taskId,
|
|
720
|
+
workspaceId,
|
|
721
|
+
asset,
|
|
722
|
+
beforeTask: taskBeforeLink,
|
|
723
|
+
createdAt: asset.updatedAt,
|
|
724
|
+
});
|
|
725
|
+
}
|
|
635
726
|
}
|
|
636
727
|
core.notifyDocumentMetadataMutation(workspaceId, [params.relativeToStorage], 'upsert');
|
|
637
728
|
}
|
|
@@ -1109,6 +1200,8 @@ export function createRoutes(core, context = {}) {
|
|
|
1109
1200
|
authenticatedViaOAuth: oauthAuth || null,
|
|
1110
1201
|
userId: null,
|
|
1111
1202
|
...bootstrap,
|
|
1203
|
+
aiProfileToken: bootstrap.aiProfileToken || oauthAuth?.aiProfileToken || null,
|
|
1204
|
+
aiProfileName: bootstrap.aiProfileName || oauthAuth?.aiProfileName || null,
|
|
1112
1205
|
};
|
|
1113
1206
|
}
|
|
1114
1207
|
core.addMcpAuditLog({
|
|
@@ -1348,6 +1441,7 @@ export function createRoutes(core, context = {}) {
|
|
|
1348
1441
|
return;
|
|
1349
1442
|
}
|
|
1350
1443
|
const authScopes = auth.authenticatedViaToken?.scopes || auth.authenticatedViaOAuth?.scopes || [];
|
|
1444
|
+
const requestId = String(req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || randomUUID();
|
|
1351
1445
|
const deniedToolName = findDeniedCloudMcpToolName(body, authScopes);
|
|
1352
1446
|
if (deniedToolName) {
|
|
1353
1447
|
core.addMcpAuditLog({
|
|
@@ -1357,7 +1451,7 @@ export function createRoutes(core, context = {}) {
|
|
|
1357
1451
|
tokenId: auth.authenticatedViaToken?.tokenId || auth.authenticatedViaOAuth?.grantId || null,
|
|
1358
1452
|
toolName: deniedToolName,
|
|
1359
1453
|
details: {
|
|
1360
|
-
requestId
|
|
1454
|
+
requestId,
|
|
1361
1455
|
ip: req.socket?.remoteAddress || null,
|
|
1362
1456
|
userAgent: requestHeader(req, 'user-agent', '') || null,
|
|
1363
1457
|
outcome: 'deny',
|
|
@@ -1371,11 +1465,13 @@ export function createRoutes(core, context = {}) {
|
|
|
1371
1465
|
if (!applyCloudMcpWriteRateLimit(req, res, auth, body)) {
|
|
1372
1466
|
return;
|
|
1373
1467
|
}
|
|
1468
|
+
let runtime = null;
|
|
1374
1469
|
try {
|
|
1375
|
-
|
|
1470
|
+
runtime = createTaskforceMcpServer({
|
|
1376
1471
|
projectRoot: core.getPaths().projectRoot,
|
|
1377
1472
|
tenantId: core.getTenantId(),
|
|
1378
1473
|
workspaceId: auth.workspaceId,
|
|
1474
|
+
core: core,
|
|
1379
1475
|
serverName: 'taskforce-cloud',
|
|
1380
1476
|
logStartup: false,
|
|
1381
1477
|
runtimeMode: 'cloud',
|
|
@@ -1383,7 +1479,7 @@ export function createRoutes(core, context = {}) {
|
|
|
1383
1479
|
req,
|
|
1384
1480
|
auth,
|
|
1385
1481
|
requestHeader,
|
|
1386
|
-
requestId
|
|
1482
|
+
requestId,
|
|
1387
1483
|
authScopes,
|
|
1388
1484
|
}),
|
|
1389
1485
|
});
|
|
@@ -1398,13 +1494,29 @@ export function createRoutes(core, context = {}) {
|
|
|
1398
1494
|
}
|
|
1399
1495
|
await transport.handleRequest(req, res, body);
|
|
1400
1496
|
recordCloudMcpCredentialUsage(req, auth.authenticatedViaToken, auth.authenticatedViaOAuth);
|
|
1401
|
-
await transport.close().catch(() => undefined);
|
|
1402
|
-
await runtime.server.close().catch(() => undefined);
|
|
1403
1497
|
}
|
|
1404
1498
|
catch (error) {
|
|
1405
|
-
console.error('[Taskforce MCP] Cloud transport request failed:',
|
|
1499
|
+
console.error('[Taskforce MCP] Cloud transport request failed:', {
|
|
1500
|
+
requestId,
|
|
1501
|
+
kind: 'tool_transport_failure',
|
|
1502
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1503
|
+
});
|
|
1406
1504
|
if (!res.headersSent) {
|
|
1407
|
-
writeMcpHttpError(res, 500, '
|
|
1505
|
+
writeMcpHttpError(res, 500, 'MCP transport failure.', {
|
|
1506
|
+
kind: 'tool_transport_failure',
|
|
1507
|
+
retryable: true,
|
|
1508
|
+
requestId,
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
finally {
|
|
1513
|
+
if (runtime) {
|
|
1514
|
+
try {
|
|
1515
|
+
await runtime.server.close();
|
|
1516
|
+
}
|
|
1517
|
+
catch (closeError) {
|
|
1518
|
+
console.warn('[Taskforce MCP] Cloud transport cleanup failed:', closeError);
|
|
1519
|
+
}
|
|
1408
1520
|
}
|
|
1409
1521
|
}
|
|
1410
1522
|
};
|
|
@@ -1412,7 +1524,26 @@ export function createRoutes(core, context = {}) {
|
|
|
1412
1524
|
const auditAdminAction = makeAuditAdminAction(core, context);
|
|
1413
1525
|
const auditAuthAction = makeAuditAuthAction(core, requestWorkspaceId, context);
|
|
1414
1526
|
const ensureAdminRole = makeEnsureAdminRole(core, context);
|
|
1415
|
-
const ensureAuthenticatedUser = makeEnsureAuthenticatedUser();
|
|
1527
|
+
const ensureAuthenticatedUser = makeEnsureAuthenticatedUser(context.authConfig);
|
|
1528
|
+
const ensureWorkspaceAdminRole = (req, workspaceIdOverride) => {
|
|
1529
|
+
const hasWorkspaceOverride = typeof workspaceIdOverride === 'string' && workspaceIdOverride.trim().length > 0;
|
|
1530
|
+
const workspaceId = String(hasWorkspaceOverride ? workspaceIdOverride : requestWorkspaceId(req) || '').trim() || 'default';
|
|
1531
|
+
const userId = String(resolveAuthenticatedUserId(req) || '').trim();
|
|
1532
|
+
if (userId && userId !== 'anonymous') {
|
|
1533
|
+
const membership = core.listWorkspaceUsers(workspaceId).find((user) => String(user.userId || '').trim() === userId);
|
|
1534
|
+
if (membership) {
|
|
1535
|
+
const role = String(membership.role || '').trim().toLowerCase();
|
|
1536
|
+
const status = String(membership.status || '').trim().toLowerCase();
|
|
1537
|
+
return membership.disabled !== true
|
|
1538
|
+
&& status === 'active'
|
|
1539
|
+
&& (role === 'owner' || role === 'admin');
|
|
1540
|
+
}
|
|
1541
|
+
if (hasWorkspaceOverride)
|
|
1542
|
+
return false;
|
|
1543
|
+
}
|
|
1544
|
+
const fallbackRole = String(requestRole(req) || '').trim().toLowerCase();
|
|
1545
|
+
return fallbackRole === 'owner' || fallbackRole === 'admin';
|
|
1546
|
+
};
|
|
1416
1547
|
const isCollaborationPolicyEnabled = () => {
|
|
1417
1548
|
const rawDefault = String(process.env.TASKFORCE_COLLAB_POLICY_V1 || 'true').trim().toLowerCase();
|
|
1418
1549
|
const envDefaultEnabled = !(rawDefault === '0' || rawDefault === 'false' || rawDefault === 'off' || rawDefault === 'no');
|
|
@@ -1464,6 +1595,7 @@ export function createRoutes(core, context = {}) {
|
|
|
1464
1595
|
context,
|
|
1465
1596
|
requestWorkspaceId,
|
|
1466
1597
|
requestUserId,
|
|
1598
|
+
resolveAuthenticatedUserId,
|
|
1467
1599
|
requestRole,
|
|
1468
1600
|
ensureAppAccess,
|
|
1469
1601
|
ensureAuthenticatedUser,
|
|
@@ -1474,6 +1606,10 @@ export function createRoutes(core, context = {}) {
|
|
|
1474
1606
|
resolveAdminRequestActor,
|
|
1475
1607
|
resolveEffectiveObjectStorageConfig,
|
|
1476
1608
|
getObjectStorageClient,
|
|
1609
|
+
workspaceAssetStore,
|
|
1610
|
+
ensureWithinDir,
|
|
1611
|
+
markAssetDeleted,
|
|
1612
|
+
appendStorageTelemetry,
|
|
1477
1613
|
});
|
|
1478
1614
|
registerWorkspaceRoutes({
|
|
1479
1615
|
addRoute,
|