@taskforcehq/taskforce 0.3.327 → 0.3.329
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Taskforce.module.css +257 -87
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/activity/EntityActivityTimeline.js +15 -5
- package/dist/components/context/AttachmentPreviewHost.js +1 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
- package/dist/components/context/ContextAttachmentManager.js +116 -20
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +147 -40
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
- package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
- package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
- package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
- package/dist/components/features/planning/PlanningModule.js +28 -14
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
- package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/task/TaskActionHeader.d.ts +2 -1
- package/dist/components/task/TaskActionHeader.js +2 -2
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +101 -13
- package/dist/components/task/TaskContextUpload.d.ts +3 -0
- package/dist/components/task/TaskContextUpload.js +2 -2
- package/dist/components/task/TaskForm.d.ts +4 -0
- package/dist/components/task/TaskForm.js +32 -7
- package/dist/components/task/TaskImageReviews.js +28 -19
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/task/TaskStatusActions.js +11 -2
- package/dist/components/task/TaskWorkstreamPicker.js +2 -1
- package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
- package/dist/components/ui/DocumentTypeIcon.js +8 -0
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
- package/dist/components/ui/TaxonomyDropdown.js +30 -3
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +68 -39
- package/dist/components/views/WidgetView.js +10 -7
- package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
- package/dist/components/views/panels/PlanningDrawer.js +51 -54
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/config/envSchema.js +13 -0
- package/dist/config/localServiceCloudTarget.d.ts +10 -0
- package/dist/config/localServiceCloudTarget.js +76 -0
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.d.ts +1 -0
- package/dist/core/AiProfileService.js +48 -9
- package/dist/core/AttachmentLinkService.js +7 -4
- package/dist/core/DeletedTaskLifecycleService.d.ts +5 -0
- package/dist/core/DeletedTaskLifecycleService.js +55 -3
- package/dist/core/McpTokenService.d.ts +4 -0
- package/dist/core/McpTokenService.js +52 -0
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +8 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +51 -18
- package/dist/core/Taskforce.d.ts +124 -2
- package/dist/core/Taskforce.js +1175 -87
- package/dist/core/types.d.ts +8 -1
- package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
- package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
- package/dist/documentReviews/service.d.ts +4 -0
- package/dist/documentReviews/service.js +141 -46
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +9 -0
- package/dist/hooks/tasks/useTaskFormActions.js +96 -17
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useTaskData.d.ts +10 -1
- package/dist/hooks/useTaskData.js +216 -7
- package/dist/hooks/useTaskMutations.d.ts +10 -2
- package/dist/hooks/useTaskMutations.js +223 -43
- package/dist/hooks/useTaskforce.d.ts +94 -57
- package/dist/hooks/useTaskforce.js +428 -16
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
- package/dist/mcp/canonicalAssetHelpers.js +39 -5
- package/dist/mcp/collaborationRegistrar.js +15 -13
- package/dist/mcp/documentAssetRegistrar.js +60 -44
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/localServiceProxy.js +4 -1
- package/dist/mcp/runtime.d.ts +16 -0
- package/dist/mcp/runtime.js +735 -210
- package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
- package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
- package/dist/mcp/taskPlanningRegistrar.js +78 -67
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +2 -2
- package/dist/migrations/taskSchemaMigrations.js +47 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +12 -13
- package/dist/runtime/appGates.js +29 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/appAccess.d.ts +12 -0
- package/dist/server/appAccess.js +21 -0
- package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
- package/dist/server/authorizedWorkspaceAccess.js +40 -0
- package/dist/server/cloudCollectionRead.d.ts +25 -0
- package/dist/server/cloudCollectionRead.js +120 -0
- package/dist/server/cloudCollectionReadPool.d.ts +52 -0
- package/dist/server/cloudCollectionReadPool.js +140 -0
- package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
- package/dist/server/cloudCollectionReadWorker.js +36 -0
- package/dist/server/index.d.ts +6 -11
- package/dist/server/index.js +67 -42
- package/dist/server/localServiceLease.d.ts +6 -0
- package/dist/server/localServiceLease.js +17 -1
- package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.js +1 -0
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.js +118 -16
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/documents.d.ts +5 -2
- package/dist/server/routes/documents.js +160 -13
- package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
- package/dist/server/routes/durableTaskHttpRouters.js +2 -2
- package/dist/server/routes/localService.js +4 -0
- package/dist/server/routes/primitives.d.ts +4 -0
- package/dist/server/routes/shared.d.ts +24 -0
- package/dist/server/routes/shared.js +114 -18
- package/dist/server/routes/sync.js +22 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncV3FeedRoutes.js +22 -18
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +48 -4
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +27 -2
- package/dist/server/routes/tasks.js +299 -97
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/routes.js +35 -7
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +52 -25
- package/dist/service/localServiceClientLifecycle.js +93 -6
- package/dist/services/codexAppServerModelGateway.d.ts +112 -0
- package/dist/services/codexAppServerModelGateway.js +438 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
- package/dist/services/taskforceAgentMcpBridge.js +23 -3
- package/dist/shared/planningIdentity.d.ts +20 -0
- package/dist/shared/planningIdentity.js +79 -0
- package/dist/shared/taskforceAgentDefinition.js +7 -1
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +30 -1
- package/dist/storage/postgresAdapter.d.ts +20 -3
- package/dist/storage/postgresAdapter.js +110 -14
- package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
- package/dist/storage/postgresRequestDiagnostics.js +24 -0
- package/dist/storage/postgresWorker.js +13 -4
- package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/storage/workspaceAssetStore.d.ts +32 -0
- package/dist/storage/workspaceAssetStore.js +70 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +17 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +77 -23
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +16 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +46 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +51 -11
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
- package/dist/sync/syncApplyHandlers.d.ts +3 -1
- package/dist/sync/syncApplyHandlers.js +29 -0
- package/dist/sync/syncService.d.ts +2 -0
- package/dist/sync/syncService.js +13 -1
- package/dist/sync/taskSyncPayload.d.ts +1 -0
- package/dist/sync/taskSyncPayload.js +6 -0
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +3 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +31 -3
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +47 -12
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
- package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
- package/dist/sync/v3/localOutboxDispatcher.js +5 -1
- package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +3 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +62 -10
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
- package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
- package/dist/sync/v3/syncDurabilityStore.d.ts +15 -0
- package/dist/sync/v3/syncDurabilityStore.js +201 -43
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +7 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +37 -12
- package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
- package/dist/sync/v3/taskChecklistMutationService.js +4 -0
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
- package/dist/sync/v3/taskStatusMutationService.js +4 -0
- package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
- package/dist/sync/v3/workflowAssignmentSync.js +3 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +14 -12
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +10 -1
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +15 -4
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +66 -13
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +57 -22
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +10 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -51
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +120 -28
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
- package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
- package/dist/sync/workspacePullFeed.d.ts +6 -1
- package/dist/sync/workspacePullFeed.js +174 -162
- package/dist/sync/workspaceRepair.d.ts +3 -0
- package/dist/sync/workspaceRepair.js +67 -6
- package/dist/sync/workspaceSyncModel.d.ts +11 -0
- package/dist/sync/workspaceSyncModel.js +27 -2
- package/dist/types.d.ts +55 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/AssetTraySortControl-C8Rztyal.js +1 -0
- package/dist/ui/assets/ContextAttachmentManager-Cj3c7X9y.js +3 -0
- package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-B5uvzems.js} +4 -4
- package/dist/ui/assets/EntityActivityTimeline-BVFvCB5R.js +1 -0
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
- package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
- package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
- package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
- package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
- package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
- package/dist/ui/assets/WorkflowManagerModule-DEr5di_r.js +1 -0
- package/dist/ui/assets/index-I5zhdtgt.js +7 -0
- package/dist/ui/assets/index-VRFsx3wz.css +1 -0
- package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-D9Lpw-j4.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/constants.d.ts +2 -2
- package/dist/utils/constants.js +1 -1
- package/dist/utils/contextAttachmentUpload.d.ts +2 -0
- package/dist/utils/contextAttachmentUpload.js +7 -0
- package/dist/utils/contextFiles.d.ts +1 -1
- package/dist/utils/contextFiles.js +4 -4
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/package.json +21 -4
- package/dist/ui/assets/AiProfilesModule-DPxQeF9N.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DHNYaNg6.js +0 -3
- package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
- package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
- package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
- package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
- package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
- package/dist/ui/assets/PlansPage-BVH_NfgT.js +0 -1
- package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
- package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
- package/dist/ui/assets/TaskSettings-xVsxSa0g.js +0 -12
- package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
- package/dist/ui/assets/index-BzJlVnNS.css +0 -1
- package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
|
@@ -10,8 +10,9 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
10
10
|
actorRef: string;
|
|
11
11
|
root: {
|
|
12
12
|
enabled: boolean;
|
|
13
|
+
hasCommittedOperation(): boolean;
|
|
13
14
|
create(candidate: unknown): import("../../core/Taskforce.js").TaskItem;
|
|
14
|
-
update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed"): import("../../core/Taskforce.js").TaskItem;
|
|
15
|
+
update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed", expectedDetailRevision?: string): import("../../core/Taskforce.js").TaskItem;
|
|
15
16
|
runBatch<T>(routeInput: string, request: unknown, apply: (context: {
|
|
16
17
|
runChild<R>(mutation: () => R): R;
|
|
17
18
|
deferPostCommitNotification(notify: () => void): void;
|
|
@@ -41,6 +42,7 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
41
42
|
replace(args: {
|
|
42
43
|
taskId: string;
|
|
43
44
|
items: readonly Partial<import("../../core/Taskforce.js").ChecklistItem>[];
|
|
45
|
+
expectedDetailRevision?: string;
|
|
44
46
|
}): {
|
|
45
47
|
state: "pending" | "committed";
|
|
46
48
|
route: "local-outbox" | "cloud-acceptance";
|
|
@@ -53,6 +55,8 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
53
55
|
replace(args: {
|
|
54
56
|
taskId: string;
|
|
55
57
|
links: readonly import("../../sync/v3/workspaceSyncV3NestedTaskCodecs.js").WorkspaceSyncV3TaskAttachmentLink[];
|
|
58
|
+
cardCoverAssetId?: string | null;
|
|
59
|
+
expectedDetailRevision?: string;
|
|
56
60
|
}): {
|
|
57
61
|
state: "pending" | "committed";
|
|
58
62
|
route: "local-outbox" | "cloud-acceptance";
|
|
@@ -65,6 +69,7 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
65
69
|
replace(args: {
|
|
66
70
|
taskId: string;
|
|
67
71
|
items: readonly Partial<import("../../core/Taskforce.js").ChecklistItem>[];
|
|
72
|
+
expectedDetailRevision?: string;
|
|
68
73
|
}): {
|
|
69
74
|
state: "pending" | "committed";
|
|
70
75
|
route: "local-outbox" | "cloud-acceptance";
|
|
@@ -77,6 +82,8 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
77
82
|
replace(args: {
|
|
78
83
|
taskId: string;
|
|
79
84
|
links: readonly import("../../sync/v3/workspaceSyncV3NestedTaskCodecs.js").WorkspaceSyncV3TaskAttachmentLink[];
|
|
85
|
+
cardCoverAssetId?: string | null;
|
|
86
|
+
expectedDetailRevision?: string;
|
|
80
87
|
}): {
|
|
81
88
|
state: "pending" | "committed";
|
|
82
89
|
route: "local-outbox" | "cloud-acceptance";
|
|
@@ -132,6 +139,7 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
132
139
|
}>, options?: {
|
|
133
140
|
saveSource?: "manual" | "autosave";
|
|
134
141
|
atomicItemFailures?: boolean;
|
|
142
|
+
expectedDetailRevision?: string;
|
|
135
143
|
}): {
|
|
136
144
|
preview: import("../../core/Taskforce.js").BulkUpdateFieldsPreview;
|
|
137
145
|
results: import("../../core/Taskforce.js").TaskItem[];
|
|
@@ -147,8 +155,9 @@ export declare function createTaskHttpDurableRouters(input: {
|
|
|
147
155
|
};
|
|
148
156
|
createRootRouter: (operationId?: string, deferPostCommitNotification?: (notify: () => void) => void) => {
|
|
149
157
|
enabled: boolean;
|
|
158
|
+
hasCommittedOperation(): boolean;
|
|
150
159
|
create(candidate: unknown): import("../../core/Taskforce.js").TaskItem;
|
|
151
|
-
update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed"): import("../../core/Taskforce.js").TaskItem;
|
|
160
|
+
update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed", expectedDetailRevision?: string): import("../../core/Taskforce.js").TaskItem;
|
|
152
161
|
runBatch<T>(routeInput: string, request: unknown, apply: (context: {
|
|
153
162
|
runChild<R>(mutation: () => R): R;
|
|
154
163
|
deferPostCommitNotification(notify: () => void): void;
|
|
@@ -4,12 +4,12 @@ import { createDurableTaskHttpRootMutationRouter } from '../../sync/v3/durableTa
|
|
|
4
4
|
import { createDurableTaskCommentMutationRouter } from '../../sync/v3/durableTaskCommentMutationRouter.js';
|
|
5
5
|
import { createDurableTaskChecklistMutationRouter } from '../../sync/v3/durableTaskChecklistMutationRouter.js';
|
|
6
6
|
import { createDurableTaskAttachmentLinksMutationRouter } from '../../sync/v3/durableTaskAttachmentLinksMutationRouter.js';
|
|
7
|
-
import { requestHeader,
|
|
7
|
+
import { requestHeader, requestHumanActorRef, requestRuntimeMode } from './shared.js';
|
|
8
8
|
export function createTaskHttpDurableRouters(input) {
|
|
9
9
|
const { core, context, req, workspaceId } = input;
|
|
10
10
|
const runtimeMode = context.authConfig?.runtimeMode === 'cloud' ? 'cloud' : requestRuntimeMode(req);
|
|
11
11
|
const parentOperationId = requestHeader(req, 'x-taskforce-operation-id', '').trim();
|
|
12
|
-
const actorRef =
|
|
12
|
+
const actorRef = requestHumanActorRef(req);
|
|
13
13
|
const createRootRouter = (operationId = parentOperationId, deferPostCommitNotification) => createDurableTaskHttpRootMutationRouter({
|
|
14
14
|
core,
|
|
15
15
|
runtimeMode,
|
|
@@ -185,6 +185,8 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
185
185
|
endpoint: context.endpoint?.() || null,
|
|
186
186
|
projectIdentity: context.projectIdentity,
|
|
187
187
|
dataIdentity: context.ownershipKey,
|
|
188
|
+
cloudTarget: context.cloudTarget,
|
|
189
|
+
runtimeContract: context.runtimeContract,
|
|
188
190
|
transports: ['streamable-http'],
|
|
189
191
|
health: {
|
|
190
192
|
lifecycle: context.sessions.state(),
|
|
@@ -279,6 +281,8 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
279
281
|
generation: context.generation,
|
|
280
282
|
protocolVersion: context.protocolVersion,
|
|
281
283
|
ownerPid: context.ownerPid,
|
|
284
|
+
cloudTarget: context.cloudTarget,
|
|
285
|
+
runtimeContract: context.runtimeContract,
|
|
282
286
|
sessions: context.sessions.list(),
|
|
283
287
|
...(context.diagnostics?.() || {}),
|
|
284
288
|
});
|
|
@@ -4,6 +4,8 @@ import type { ResolvedObjectStorageConfig } from '../../storage/objectStorage.js
|
|
|
4
4
|
import type { LocalSyncCoordinatorRouteServices } from '../../sync/coordinator/localSyncCoordinatorRouteServices.js';
|
|
5
5
|
import type { WorkspaceSyncServerDataServices } from '../../sync/engine/workspaceSyncServerDataServices.js';
|
|
6
6
|
import type { LocalServiceSessionManager } from '../localServiceSessions.js';
|
|
7
|
+
import type { LocalServiceCloudTarget } from '../../config/localServiceCloudTarget.js';
|
|
8
|
+
import type { LocalServiceRuntimeContract } from '../../config/localServiceRuntimeContract.js';
|
|
7
9
|
export interface LocalServiceRouteContext {
|
|
8
10
|
generation: string;
|
|
9
11
|
protocolVersion: string;
|
|
@@ -11,6 +13,8 @@ export interface LocalServiceRouteContext {
|
|
|
11
13
|
ownerPid: number;
|
|
12
14
|
bootstrapCapability: string;
|
|
13
15
|
ownershipKey: string;
|
|
16
|
+
cloudTarget: LocalServiceCloudTarget;
|
|
17
|
+
runtimeContract: LocalServiceRuntimeContract;
|
|
14
18
|
projectIdentity: string;
|
|
15
19
|
operationClientId: string;
|
|
16
20
|
sessions: LocalServiceSessionManager;
|
|
@@ -11,6 +11,7 @@ import type { McpAccessTokenAuthResult, McpOAuthAccessTokenAuthResult, McpAccess
|
|
|
11
11
|
import { type RouteContext } from './primitives.js';
|
|
12
12
|
import { type AiProfileBootstrapConfig } from '../../mcp/aiProfileBootstrap.js';
|
|
13
13
|
import type { AiProfileSeatScope } from '../../shared/aiProfileSeatScope.js';
|
|
14
|
+
import { type RequestPerformanceDiagnostics } from '../../storage/postgresRequestDiagnostics.js';
|
|
14
15
|
export declare function resolveErrorStatusCode(error: unknown, fallback?: number): number;
|
|
15
16
|
export declare function buildCloudMcpProfileConnectionId(input: {
|
|
16
17
|
oauth?: McpOAuthAccessTokenAuthResult | null;
|
|
@@ -19,6 +20,7 @@ export declare function buildCloudMcpProfileConnectionId(input: {
|
|
|
19
20
|
}): string | null;
|
|
20
21
|
export declare const BOOTSTRAP_ROUTE_SLOW_THRESHOLD_MS = 1500;
|
|
21
22
|
export declare const BOOTSTRAP_ROUTE_SEVERE_THRESHOLD_MS = 5000;
|
|
23
|
+
export declare const TASKFORCE_PERFORMANCE_TRACE_HEADER = "x-taskforce-performance-trace";
|
|
22
24
|
export type ServerTimingMetric = {
|
|
23
25
|
name: string;
|
|
24
26
|
durationMs: number;
|
|
@@ -31,6 +33,17 @@ export declare function serializeJsonWithTiming(payload: unknown, startedAt?: nu
|
|
|
31
33
|
byteLength: number;
|
|
32
34
|
durationMs: number;
|
|
33
35
|
};
|
|
36
|
+
export declare function runWithPerformanceTrace<T>(req: IncomingMessage, callback: () => T): T;
|
|
37
|
+
export declare function currentPerformanceTraceDiagnostics(): RequestPerformanceDiagnostics | null;
|
|
38
|
+
export declare function performanceTraceServerTimingMetrics(diagnostics: RequestPerformanceDiagnostics | null): ServerTimingMetric[];
|
|
39
|
+
export declare function setPerformanceTraceHeaders(res: ServerResponse, diagnostics: RequestPerformanceDiagnostics | null, responseBytes: number): void;
|
|
40
|
+
export declare function respondWithPerformanceTraceJson(input: {
|
|
41
|
+
req: IncomingMessage;
|
|
42
|
+
res: ServerResponse;
|
|
43
|
+
route: string;
|
|
44
|
+
workspaceId: string;
|
|
45
|
+
load: () => unknown;
|
|
46
|
+
}): void;
|
|
34
47
|
export declare function requestBootstrapTraceId(req: IncomingMessage): string;
|
|
35
48
|
export declare function logSlowBootstrapRoute(input: {
|
|
36
49
|
route: string;
|
|
@@ -47,6 +60,7 @@ export declare function buildCloudMcpRuntimeAuth(input: {
|
|
|
47
60
|
authenticatedViaToken: McpAccessTokenAuthResult | null;
|
|
48
61
|
authenticatedViaOAuth: McpOAuthAccessTokenAuthResult | null;
|
|
49
62
|
userId: string | null;
|
|
63
|
+
aiProfileIdentityAsserted?: boolean;
|
|
50
64
|
} & Required<AiProfileBootstrapConfig>;
|
|
51
65
|
requestHeader: (req: IncomingMessage, name: string, fallback?: string) => string;
|
|
52
66
|
requestId?: string | null;
|
|
@@ -57,6 +71,7 @@ export declare function buildCloudMcpRuntimeAuth(input: {
|
|
|
57
71
|
tokenId?: string | null;
|
|
58
72
|
aiProfileToken?: AiProfileBootstrapConfig['aiProfileToken'];
|
|
59
73
|
aiProfileId?: string | null;
|
|
74
|
+
aiProfileIdentityAsserted?: boolean;
|
|
60
75
|
aiProfileName?: AiProfileBootstrapConfig['aiProfileName'];
|
|
61
76
|
aiProfileIcon?: AiProfileBootstrapConfig['aiProfileIcon'];
|
|
62
77
|
aiProfileColor?: AiProfileBootstrapConfig['aiProfileColor'];
|
|
@@ -79,6 +94,7 @@ export type CloudMcpRequestAuth = {
|
|
|
79
94
|
authenticatedViaOAuth: McpOAuthAccessTokenAuthResult | null;
|
|
80
95
|
userId: string | null;
|
|
81
96
|
aiProfileId?: string | null;
|
|
97
|
+
aiProfileIdentityAsserted?: boolean;
|
|
82
98
|
} & Required<AiProfileBootstrapConfig>;
|
|
83
99
|
export declare function makeAuthenticateCloudMcpRequest(core: TaskforceCore, deps: {
|
|
84
100
|
resolveAuthenticatedUserId: (req: IncomingMessage) => string;
|
|
@@ -101,6 +117,14 @@ export declare function requestRuntimeMode(req: IncomingMessage): 'local' | 'clo
|
|
|
101
117
|
export declare function requestRole(req: IncomingMessage): string;
|
|
102
118
|
export declare function requestSystemRole(req: IncomingMessage): 'system_admin' | 'user';
|
|
103
119
|
export declare function requestUserId(req: IncomingMessage): string;
|
|
120
|
+
/**
|
|
121
|
+
* Resolve the human actor recorded by ordinary HTTP mutations. The standalone
|
|
122
|
+
* server has already replaced this header with authenticated cloud identity
|
|
123
|
+
* when available; local signed-in clients provide the same account id through
|
|
124
|
+
* the request-scoped mutation header. Anonymous sessions retain the legacy
|
|
125
|
+
* generic actor for compatibility.
|
|
126
|
+
*/
|
|
127
|
+
export declare function requestHumanActorRef(req: IncomingMessage): string;
|
|
104
128
|
export declare function makeRequestWorkspaceId(core: TaskforceCore, context: RouteContext): (req: IncomingMessage) => string;
|
|
105
129
|
export declare function makeResolveAuthenticatedUserId(core: TaskforceCore, context: RouteContext, requestWorkspaceId: (req: IncomingMessage) => string): (req: IncomingMessage) => string;
|
|
106
130
|
export declare function makeResolveAuthenticatedMutationUserId(core: TaskforceCore, context: RouteContext, requestWorkspaceId: (req: IncomingMessage) => string): (req: IncomingMessage) => string;
|
|
@@ -17,7 +17,9 @@ import { resolveCanonicalMcpToolName } from '../../mcp/toolCallCompatibility.js'
|
|
|
17
17
|
import { applyPrefixedRateLimitHeaders } from '../rateLimit.js';
|
|
18
18
|
import { parseAiProfileBootstrapHeaders } from '../../mcp/aiProfileBootstrap.js';
|
|
19
19
|
import { parseMcpClientId } from '../../mcp/clientRegistry.js';
|
|
20
|
+
import { resolveAppAccessDeniedResponse } from '../appAccess.js';
|
|
20
21
|
import { resolveCloudApplicationBaseUrl } from '../../config/applicationBaseUrl.js';
|
|
22
|
+
import { getRequestPerformanceDiagnostics, runWithRequestPerformanceDiagnostics, } from '../../storage/postgresRequestDiagnostics.js';
|
|
21
23
|
// === SECTION: Error helpers ===
|
|
22
24
|
export function resolveErrorStatusCode(error, fallback = 400) {
|
|
23
25
|
if (error instanceof TaskforceRuleError)
|
|
@@ -39,6 +41,7 @@ export function buildCloudMcpProfileConnectionId(input) {
|
|
|
39
41
|
// === SECTION: Route timing helpers ===
|
|
40
42
|
export const BOOTSTRAP_ROUTE_SLOW_THRESHOLD_MS = 1500;
|
|
41
43
|
export const BOOTSTRAP_ROUTE_SEVERE_THRESHOLD_MS = 5000;
|
|
44
|
+
export const TASKFORCE_PERFORMANCE_TRACE_HEADER = 'x-taskforce-performance-trace';
|
|
42
45
|
function sanitizeServerTimingMetricName(name) {
|
|
43
46
|
return String(name || 'taskforce-route')
|
|
44
47
|
.trim()
|
|
@@ -68,6 +71,55 @@ export function serializeJsonWithTiming(payload, startedAt = getRouteTimingNow()
|
|
|
68
71
|
durationMs: Math.max(0, getRouteTimingNow() - startedAt),
|
|
69
72
|
};
|
|
70
73
|
}
|
|
74
|
+
export function runWithPerformanceTrace(req, callback) {
|
|
75
|
+
const enabled = requestHeader(req, TASKFORCE_PERFORMANCE_TRACE_HEADER, '').trim() === '1';
|
|
76
|
+
return runWithRequestPerformanceDiagnostics(enabled, callback);
|
|
77
|
+
}
|
|
78
|
+
export function currentPerformanceTraceDiagnostics() {
|
|
79
|
+
return getRequestPerformanceDiagnostics();
|
|
80
|
+
}
|
|
81
|
+
export function performanceTraceServerTimingMetrics(diagnostics) {
|
|
82
|
+
return diagnostics ? [{ name: 'postgres-worker-wait', durationMs: diagnostics.postgresWorkerWaitMs }] : [];
|
|
83
|
+
}
|
|
84
|
+
export function setPerformanceTraceHeaders(res, diagnostics, responseBytes) {
|
|
85
|
+
if (!diagnostics)
|
|
86
|
+
return;
|
|
87
|
+
res.setHeader('X-Taskforce-Postgres-Query-Count', String(diagnostics.postgresQueryCount));
|
|
88
|
+
res.setHeader('X-Taskforce-Postgres-Worker-Call-Count', String(diagnostics.postgresWorkerCallCount));
|
|
89
|
+
res.setHeader('X-Taskforce-Response-Bytes', String(responseBytes));
|
|
90
|
+
}
|
|
91
|
+
export function respondWithPerformanceTraceJson(input) {
|
|
92
|
+
runWithPerformanceTrace(input.req, () => {
|
|
93
|
+
const startedAt = getRouteTimingNow();
|
|
94
|
+
const data = input.load();
|
|
95
|
+
const loadCompletedAt = getRouteTimingNow();
|
|
96
|
+
const serialized = serializeJsonWithTiming(data);
|
|
97
|
+
const diagnostics = getRequestPerformanceDiagnostics();
|
|
98
|
+
const totalDurationMs = Math.max(0, getRouteTimingNow() - startedAt);
|
|
99
|
+
setServerTimingHeader(input.res, [
|
|
100
|
+
{ name: 'route-total', durationMs: totalDurationMs },
|
|
101
|
+
{ name: 'route-load', durationMs: loadCompletedAt - startedAt },
|
|
102
|
+
{ name: 'route-json', durationMs: serialized.durationMs },
|
|
103
|
+
...performanceTraceServerTimingMetrics(diagnostics),
|
|
104
|
+
]);
|
|
105
|
+
setPerformanceTraceHeaders(input.res, diagnostics, serialized.byteLength);
|
|
106
|
+
logSlowBootstrapRoute({
|
|
107
|
+
route: input.route,
|
|
108
|
+
workspaceId: input.workspaceId,
|
|
109
|
+
traceId: requestBootstrapTraceId(input.req),
|
|
110
|
+
durationMs: totalDurationMs,
|
|
111
|
+
details: diagnostics ? {
|
|
112
|
+
responseBytes: serialized.byteLength,
|
|
113
|
+
postgresQueryCount: diagnostics.postgresQueryCount,
|
|
114
|
+
postgresWorkerCallCount: diagnostics.postgresWorkerCallCount,
|
|
115
|
+
postgresWorkerWaitMs: Math.round(diagnostics.postgresWorkerWaitMs),
|
|
116
|
+
jsonSerializeMs: serialized.durationMs,
|
|
117
|
+
} : { responseBytes: serialized.byteLength },
|
|
118
|
+
});
|
|
119
|
+
input.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
120
|
+
input.res.end(serialized.body);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
71
123
|
export function requestBootstrapTraceId(req) {
|
|
72
124
|
return requestHeader(req, 'x-taskforce-bootstrap-trace-id', '').trim();
|
|
73
125
|
}
|
|
@@ -100,6 +152,7 @@ export function buildCloudMcpRuntimeAuth(input) {
|
|
|
100
152
|
tokenId: auth.authenticatedViaToken?.tokenId || auth.authenticatedViaOAuth?.grantId || null,
|
|
101
153
|
aiProfileToken: auth.aiProfileToken,
|
|
102
154
|
aiProfileId: auth.authenticatedViaOAuth?.aiProfileId || null,
|
|
155
|
+
aiProfileIdentityAsserted: auth.aiProfileIdentityAsserted === true,
|
|
103
156
|
aiProfileName: auth.aiProfileName,
|
|
104
157
|
aiProfileIcon: auth.aiProfileIcon,
|
|
105
158
|
aiProfileColor: auth.aiProfileColor,
|
|
@@ -183,6 +236,7 @@ export function makeAuthenticateCloudMcpRequest(core, deps) {
|
|
|
183
236
|
userId: null,
|
|
184
237
|
...bootstrap,
|
|
185
238
|
aiProfileId: oauthAuth?.aiProfileId || null,
|
|
239
|
+
aiProfileIdentityAsserted: Boolean(bootstrap.aiProfileName || bootstrap.aiProfileProvider),
|
|
186
240
|
aiProfileToken: bootstrap.aiProfileToken || oauthAuth?.aiProfileToken || null,
|
|
187
241
|
aiProfileName: bootstrap.aiProfileName || oauthAuth?.aiProfileName || null,
|
|
188
242
|
mcpClientId: oauthAuth
|
|
@@ -337,6 +391,9 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
337
391
|
};
|
|
338
392
|
return async function handleCloudMcpRequest(req, res) {
|
|
339
393
|
const requestStartedAtMs = Date.now();
|
|
394
|
+
let authMs = 0;
|
|
395
|
+
let bodyParseMs = 0;
|
|
396
|
+
let rateLimitMs = 0;
|
|
340
397
|
if (requestRuntimeMode(req) !== 'cloud') {
|
|
341
398
|
writeMcpHttpError(res, 400, 'The /mcp HTTP endpoint is only available in cloud runtime. In local runtime, use the local stdio MCP server (for example: `taskforce mcp <project-path>`).');
|
|
342
399
|
return;
|
|
@@ -347,7 +404,9 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
347
404
|
writeMcpHttpError(res, 405, 'Method not allowed.');
|
|
348
405
|
return;
|
|
349
406
|
}
|
|
407
|
+
const authStartedAtMs = Date.now();
|
|
350
408
|
const auth = authenticateCloudMcpRequest(req, res);
|
|
409
|
+
authMs = Date.now() - authStartedAtMs;
|
|
351
410
|
if (!auth)
|
|
352
411
|
return;
|
|
353
412
|
if (req.method !== 'POST') {
|
|
@@ -356,7 +415,9 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
356
415
|
}
|
|
357
416
|
let body = undefined;
|
|
358
417
|
try {
|
|
418
|
+
const bodyParseStartedAtMs = Date.now();
|
|
359
419
|
body = await parseJsonBody(req);
|
|
420
|
+
bodyParseMs = Date.now() - bodyParseStartedAtMs;
|
|
360
421
|
}
|
|
361
422
|
catch (error) {
|
|
362
423
|
writeMcpHttpError(res, resolveErrorStatusCode(error, 400), 'Invalid JSON body.');
|
|
@@ -364,6 +425,7 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
364
425
|
}
|
|
365
426
|
const authScopes = auth.authenticatedViaToken?.scopes || auth.authenticatedViaOAuth?.scopes || [];
|
|
366
427
|
const requestId = String(req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || randomUUID();
|
|
428
|
+
res.setHeader('X-Request-ID', requestId);
|
|
367
429
|
const mcpMethod = !Array.isArray(body) && body !== null && typeof body === 'object'
|
|
368
430
|
? String(body.method || '')
|
|
369
431
|
: '';
|
|
@@ -389,7 +451,11 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
389
451
|
writeMcpHttpError(res, 403, 'Forbidden.');
|
|
390
452
|
return;
|
|
391
453
|
}
|
|
392
|
-
|
|
454
|
+
const writeToolNames = extractMcpWriteToolNames(body);
|
|
455
|
+
const rateLimitStartedAtMs = Date.now();
|
|
456
|
+
const rateLimitAllowed = applyCloudMcpWriteRateLimit(req, res, auth, body);
|
|
457
|
+
rateLimitMs = Date.now() - rateLimitStartedAtMs;
|
|
458
|
+
if (!rateLimitAllowed)
|
|
393
459
|
return;
|
|
394
460
|
let runtime = null;
|
|
395
461
|
let runtimeConstructionMs = 0;
|
|
@@ -397,6 +463,7 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
397
463
|
let requestHandlingMs = 0;
|
|
398
464
|
let cleanupMs = 0;
|
|
399
465
|
let outcome = 'success';
|
|
466
|
+
const toolTimingState = { value: null };
|
|
400
467
|
try {
|
|
401
468
|
const runtimeStartedAtMs = Date.now();
|
|
402
469
|
// Intentionally isolate the MCP runtime per HTTP request. The runtime closes over
|
|
@@ -420,6 +487,25 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
420
487
|
requestId,
|
|
421
488
|
authScopes,
|
|
422
489
|
}),
|
|
490
|
+
onToolCallTiming: (timing) => {
|
|
491
|
+
toolTimingState.value = timing;
|
|
492
|
+
if (!res.headersSent) {
|
|
493
|
+
setServerTimingHeader(res, [
|
|
494
|
+
{ name: 'auth', durationMs: authMs },
|
|
495
|
+
{ name: 'body-parse', durationMs: bodyParseMs },
|
|
496
|
+
{ name: 'rate-limit', durationMs: rateLimitMs },
|
|
497
|
+
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
498
|
+
{ name: 'transport-connect', durationMs: transportConnectMs },
|
|
499
|
+
{ name: 'tool-envelope-prepare', durationMs: timing.preparationMs },
|
|
500
|
+
{ name: 'tool-envelope-validate', durationMs: timing.validationMs },
|
|
501
|
+
{ name: 'tool-handler', durationMs: timing.handlerMs },
|
|
502
|
+
...Object.entries(timing.subphases).map(([phase, durationMs]) => ({
|
|
503
|
+
name: `tool-${phase}`,
|
|
504
|
+
durationMs,
|
|
505
|
+
})),
|
|
506
|
+
]);
|
|
507
|
+
}
|
|
508
|
+
},
|
|
423
509
|
});
|
|
424
510
|
runtimeConstructionMs = Date.now() - runtimeStartedAtMs;
|
|
425
511
|
const transport = new StreamableHTTPServerTransport({
|
|
@@ -465,7 +551,8 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
465
551
|
cleanupMs = Date.now() - cleanupStartedAtMs;
|
|
466
552
|
}
|
|
467
553
|
const totalDurationMs = Date.now() - requestStartedAtMs;
|
|
468
|
-
if (initializeRequest || mcpMethod === 'tools/list' || totalDurationMs >= 250) {
|
|
554
|
+
if (initializeRequest || mcpMethod === 'tools/list' || writeToolNames.length > 0 || totalDurationMs >= 250) {
|
|
555
|
+
const timingSnapshot = toolTimingState.value;
|
|
469
556
|
console.info(`[Taskforce MCP] ${JSON.stringify({
|
|
470
557
|
event: 'cloud_request_timing',
|
|
471
558
|
requestId,
|
|
@@ -477,13 +564,23 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
477
564
|
method: mcpMethod || null,
|
|
478
565
|
toolName: extractFirstMcpToolName(body),
|
|
479
566
|
workspaceId: auth.workspaceId,
|
|
567
|
+
databaseProvider: core.getDatabaseProvider(),
|
|
568
|
+
authMode: auth.authenticatedViaToken ? 'token' : auth.authenticatedViaOAuth ? 'oauth' : 'user',
|
|
569
|
+
batchSize: Array.isArray(body) ? body.length : 1,
|
|
570
|
+
isWrite: writeToolNames.length > 0,
|
|
480
571
|
outcome,
|
|
572
|
+
httpStatus: res.statusCode,
|
|
573
|
+
responseBytes: timingSnapshot?.responseBytes ?? null,
|
|
481
574
|
totalDurationMs,
|
|
482
575
|
preRuntimeMs: Math.max(0, totalDurationMs - runtimeConstructionMs - transportConnectMs - requestHandlingMs - cleanupMs),
|
|
576
|
+
authMs,
|
|
577
|
+
bodyParseMs,
|
|
578
|
+
rateLimitMs,
|
|
483
579
|
runtimeConstructionMs,
|
|
484
580
|
transportConnectMs,
|
|
485
581
|
requestHandlingMs,
|
|
486
582
|
cleanupMs,
|
|
583
|
+
toolTiming: timingSnapshot,
|
|
487
584
|
})}`);
|
|
488
585
|
}
|
|
489
586
|
}
|
|
@@ -521,6 +618,17 @@ export function requestSystemRole(req) {
|
|
|
521
618
|
export function requestUserId(req) {
|
|
522
619
|
return requestHeader(req, 'x-taskforce-user-id', 'anonymous') || 'anonymous';
|
|
523
620
|
}
|
|
621
|
+
/**
|
|
622
|
+
* Resolve the human actor recorded by ordinary HTTP mutations. The standalone
|
|
623
|
+
* server has already replaced this header with authenticated cloud identity
|
|
624
|
+
* when available; local signed-in clients provide the same account id through
|
|
625
|
+
* the request-scoped mutation header. Anonymous sessions retain the legacy
|
|
626
|
+
* generic actor for compatibility.
|
|
627
|
+
*/
|
|
628
|
+
export function requestHumanActorRef(req) {
|
|
629
|
+
const userId = String(requestUserId(req) || '').trim();
|
|
630
|
+
return userId && userId !== 'anonymous' ? userId : 'user';
|
|
631
|
+
}
|
|
524
632
|
// === SECTION: Workspace ID resolution ===
|
|
525
633
|
export function makeRequestWorkspaceId(core, context) {
|
|
526
634
|
return function requestWorkspaceId(req) {
|
|
@@ -625,23 +733,11 @@ export function makeEnsureAppAccess(core, context) {
|
|
|
625
733
|
if (!access.authenticated || !access.userId || access.userId === 'anonymous')
|
|
626
734
|
return true;
|
|
627
735
|
const accountAccess = core.getAccountAccessStatus(access.userId);
|
|
628
|
-
|
|
736
|
+
const denied = resolveAppAccessDeniedResponse(accountAccess);
|
|
737
|
+
if (!denied)
|
|
629
738
|
return true;
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
: accountAccess.gate === 'checkout_pending'
|
|
633
|
-
? 'CHECKOUT_PENDING'
|
|
634
|
-
: accountAccess.gate === 'misconfigured'
|
|
635
|
-
? 'ACCOUNT_ACCESS_MISCONFIGURED'
|
|
636
|
-
: 'ACCOUNT_ENTITLEMENT_REQUIRED';
|
|
637
|
-
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
638
|
-
res.end(JSON.stringify({
|
|
639
|
-
error: accountAccess.message || 'This account cannot access the app.',
|
|
640
|
-
code,
|
|
641
|
-
gate: accountAccess.gate,
|
|
642
|
-
canAccessPlans: accountAccess.canAccessPlans,
|
|
643
|
-
planSelectionRequired: accountAccess.planSelectionRequired
|
|
644
|
-
}));
|
|
739
|
+
res.writeHead(denied.statusCode, { 'Content-Type': 'application/json' });
|
|
740
|
+
res.end(JSON.stringify(denied.body));
|
|
645
741
|
return false;
|
|
646
742
|
};
|
|
647
743
|
}
|
|
@@ -2,6 +2,7 @@ import { parseJsonBody } from './primitives.js';
|
|
|
2
2
|
import { resolveSessionCookieAttributesForRequest } from '../auth.js';
|
|
3
3
|
import { isAiProfileSurfaceType, parseAiProfileSurfaceType } from '../../shared/aiProfileSurfaceType.js';
|
|
4
4
|
import { isAiProfileSeatScope } from '../../shared/aiProfileSeatScope.js';
|
|
5
|
+
import { assertPlanningIdentityColor, assertPlanningIdentityIcon } from '../../shared/planningIdentity.js';
|
|
5
6
|
import { serializeBinaryAssetSyncPayload, serializeDocumentSyncPayload, } from '../../sync/contentSyncPayload.js';
|
|
6
7
|
import { normalizeAiProfileSyncPayload, normalizeAgentConversationSyncPayload, normalizeAgentRoleSyncPayload, normalizeAnnotatedAttachmentSessionSyncPayload, normalizeDocumentReviewCommentSyncPayload, normalizeDocumentReviewSessionSyncPayload, normalizeTaskforceAgentSkillSyncPayload, normalizeTaskforceAgentSyncPayload, } from '../../sync/collaborationSyncPayload.js';
|
|
7
8
|
import { normalizeInitiativeSyncPayload, normalizeTaxonomySyncPayload, normalizeWorkstreamSyncPayload, } from '../../sync/planningSyncPayload.js';
|
|
@@ -451,6 +452,27 @@ export function registerSyncRoutes(deps) {
|
|
|
451
452
|
op: 'workstream-upsert',
|
|
452
453
|
workstream
|
|
453
454
|
})),
|
|
455
|
+
...[
|
|
456
|
+
...incomingInitiatives.map((entity) => ({
|
|
457
|
+
entityType: 'initiative',
|
|
458
|
+
entityId: String(entity.id || '').trim(),
|
|
459
|
+
icon: assertPlanningIdentityIcon(entity.icon),
|
|
460
|
+
color: assertPlanningIdentityColor(entity.color),
|
|
461
|
+
updatedAt: String(entity.identityUpdatedAt || '').trim(),
|
|
462
|
+
})),
|
|
463
|
+
...incomingWorkstreams.map((entity) => ({
|
|
464
|
+
entityType: 'workstream',
|
|
465
|
+
entityId: String(entity.id || '').trim(),
|
|
466
|
+
icon: assertPlanningIdentityIcon(entity.icon),
|
|
467
|
+
color: assertPlanningIdentityColor(entity.color),
|
|
468
|
+
updatedAt: String(entity.identityUpdatedAt || '').trim(),
|
|
469
|
+
})),
|
|
470
|
+
]
|
|
471
|
+
.filter((identity) => identity.entityId.length > 0 && Number.isFinite(Date.parse(identity.updatedAt)))
|
|
472
|
+
.map((identity) => ({
|
|
473
|
+
op: 'planning-identity-upsert',
|
|
474
|
+
identity,
|
|
475
|
+
})),
|
|
454
476
|
...incomingAiProfiles
|
|
455
477
|
.map((profile) => normalizeAiProfileSyncPayload(profile, cloudWorkspaceId, normalizeIncomingAiProfileSurfaceType, normalizeIncomingAiProfileSeatScope, 'push.aiProfileUpsert'))
|
|
456
478
|
.filter((profile) => Boolean(profile && profile.id.length > 0))
|
|
@@ -50,8 +50,11 @@ export function registerWorkspaceSyncAuxRoutes({ addRoute, core, context, resolv
|
|
|
50
50
|
res.end(JSON.stringify({ success: true }));
|
|
51
51
|
});
|
|
52
52
|
// POST /api/taskforce/sync/workspace/repair-startup - Auto-repair workspace asset/document
|
|
53
|
-
// metadata on workspace open. Safe fixups re-register metadata for local files and
|
|
54
|
-
// stale
|
|
53
|
+
// metadata on workspace open. Safe fixups re-register metadata for local files and clean up
|
|
54
|
+
// stale links. Does NOT tombstone metadata for files that appear missing locally — a single
|
|
55
|
+
// failed existence check at startup can mean the content is only temporarily unavailable
|
|
56
|
+
// (e.g. storage not yet mounted/synced), not deleted; that requires explicit admin
|
|
57
|
+
// confirmation via /api/taskforce/admin/workspace-repair/apply. Never deletes files.
|
|
55
58
|
// Called once by the sync orchestrator when the workspace becomes active.
|
|
56
59
|
addRoute('POST', '/api/taskforce/sync/workspace/repair-startup', async (req, res) => {
|
|
57
60
|
const authConfig = context.authConfig;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_WORKSPACE_PULL_PAGE_MAX_BYTES, buildWorkspacePullFeed, WorkspacePullEntryTooLargeError, } from '../../sync/workspacePullFeed.js';
|
|
2
2
|
import { applyWorkspaceSyncLocalBatch } from '../../sync/engine/workspaceSyncEngineLocalApply.js';
|
|
3
3
|
import { parseJsonBody } from './primitives.js';
|
|
4
|
-
import { normalizeWorkspaceSyncV2ProjectionExclusions, parseWorkspaceSyncV2ProjectionExclusions, WORKSPACE_SYNC_V3_COMBINED_V2_EXCLUSIONS, } from '../../sync/v3/workspaceSyncV2ProjectionExclusions.js';
|
|
4
|
+
import { normalizeWorkspaceSyncV2ProjectionExclusions, parseWorkspaceSyncV2ProjectionExclusions, WORKSPACE_SYNC_V3_COMBINED_V2_EXCLUSIONS, workspaceSyncV2ProjectionExclusionsEqual, } from '../../sync/v3/workspaceSyncV2ProjectionExclusions.js';
|
|
5
5
|
import { resolveWorkspaceSyncV3AttestedV2Exclusions } from '../../sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js';
|
|
6
6
|
import { requireAuthenticatedSyncRequest, requireEnabledSyncAuth, resolveAuthorizedSyncWorkspace, } from './syncRouteGuards.js';
|
|
7
7
|
import { completeLocalSyncBrowserPushEchoPermitGroup, createLocalSyncBrowserV2ApplyTransactionHooks, parseLocalSyncBrowserApplyPermitContext, resolveLocalSyncBrowserApplyPermitOperationClass, } from '../../sync/coordinator/localSyncBrowserApplyPermitContext.js';
|
|
@@ -301,7 +301,16 @@ export function registerWorkspacePullApplySyncRoutes({ addRoute, core, context,
|
|
|
301
301
|
};
|
|
302
302
|
}
|
|
303
303
|
if (!change) {
|
|
304
|
-
missing.push(
|
|
304
|
+
missing.push({
|
|
305
|
+
...request,
|
|
306
|
+
disposition: request.kind === 'asset'
|
|
307
|
+
&& 'assetId' in request
|
|
308
|
+
&& (!requestedAsset
|
|
309
|
+
|| requestedAsset.deletedAt
|
|
310
|
+
|| requestedAsset.storageProvider === 'external')
|
|
311
|
+
? 'terminal-unavailable'
|
|
312
|
+
: 'retryable',
|
|
313
|
+
});
|
|
305
314
|
consumed += 1;
|
|
306
315
|
continue;
|
|
307
316
|
}
|
|
@@ -554,6 +563,16 @@ export function registerWorkspacePullApplySyncRoutes({ addRoute, core, context,
|
|
|
554
563
|
: null;
|
|
555
564
|
let applyResult;
|
|
556
565
|
if (permitContext && coordinatorServices && permitOperationClass === 'push') {
|
|
566
|
+
const attestedV2ExcludedProjections = v2ExcludedProjections.length > 0
|
|
567
|
+
? (() => {
|
|
568
|
+
const attested = resolveWorkspaceSyncV3AttestedV2Exclusions({
|
|
569
|
+
coverage: body?.combinedCoverage,
|
|
570
|
+
excludedProjections: v2ExcludedProjections,
|
|
571
|
+
runtimeMode: 'local',
|
|
572
|
+
});
|
|
573
|
+
return attested && workspaceSyncV2ProjectionExclusionsEqual(attested, v2ExcludedProjections) ? attested : null;
|
|
574
|
+
})()
|
|
575
|
+
: [];
|
|
557
576
|
applyResult = completeLocalSyncBrowserPushEchoPermitGroup({
|
|
558
577
|
services: coordinatorServices,
|
|
559
578
|
cookieHeader: req.headers.cookie,
|
|
@@ -567,13 +586,13 @@ export function registerWorkspacePullApplySyncRoutes({ addRoute, core, context,
|
|
|
567
586
|
|| workspaceMembers !== undefined
|
|
568
587
|
|| body?.bootstrapSnapshot !== undefined
|
|
569
588
|
|| allowReferenceNumberReassignment
|
|
570
|
-
||
|
|
589
|
+
|| !attestedV2ExcludedProjections) {
|
|
571
590
|
throw new Error('Browser push echo apply accepts only authoritative task upserts.');
|
|
572
591
|
}
|
|
573
592
|
return dispatchWorkspaceSyncMetadataAtomically(workspaceId, incomingChanges, {
|
|
574
593
|
allowReferenceNumberReassignment: false,
|
|
575
594
|
coexistenceDirection: 'local-pull',
|
|
576
|
-
v2ExcludedProjections:
|
|
595
|
+
v2ExcludedProjections: attestedV2ExcludedProjections,
|
|
577
596
|
});
|
|
578
597
|
},
|
|
579
598
|
});
|
|
@@ -5,7 +5,7 @@ import { buildWorkspaceSyncV3InitiativeRepairPage, decodeWorkspaceSyncV3Initiati
|
|
|
5
5
|
import { WORKSPACE_SYNC_V3_COVERAGE_PROFILE } from '../../sync/v3/workspaceSyncV3FeedProfile.js';
|
|
6
6
|
import { isWorkspaceSyncV3InitiativeLegacyPushDisabled } from '../../sync/v3/planningActivation.js';
|
|
7
7
|
import { WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE } from '../../sync/v3/workspaceSyncV3CombinedCoverage.js';
|
|
8
|
-
import { buildWorkspaceSyncV3CombinedRepairPage, decodeWorkspaceSyncV3CombinedRepairCursor, decodeWorkspaceSyncV3NestedRepairCursor, decodeWorkspaceSyncV3PlanningOrderRepairCursor, decodeWorkspaceSyncV3WorkflowRepairCursor, WorkspaceSyncV3CombinedRepairSnapshotUnavailableError, } from '../../sync/v3/workspaceSyncV3CombinedRepairMaterialization.js';
|
|
8
|
+
import { buildWorkspaceSyncV3CombinedRepairPage, decodeWorkspaceSyncV3CombinedRepairCursor, decodeWorkspaceSyncV3NestedRepairCursor, decodeWorkspaceSyncV3PlanningOrderRepairCursor, decodeWorkspaceSyncV3TaskCoverRepairCursor, decodeWorkspaceSyncV3WorkflowRepairCursor, WorkspaceSyncV3CombinedRepairSnapshotUnavailableError, } from '../../sync/v3/workspaceSyncV3CombinedRepairMaterialization.js';
|
|
9
9
|
import { isWorkspaceSyncV3CombinedLegacyFenceEnabled } from '../../sync/v3/workspaceSyncV2ProjectionExclusions.js';
|
|
10
10
|
import { resolveCombinedFeedCapability } from '../../sync/v3/combinedFeedCapability.js';
|
|
11
11
|
import { resolveWorkspaceSyncV3RegisteredCoverage } from '../../sync/v3/workspaceSyncV3CoverageRegistry.js';
|
|
@@ -21,6 +21,17 @@ function json(res, status, body) {
|
|
|
21
21
|
res.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
22
22
|
res.end(JSON.stringify(body));
|
|
23
23
|
}
|
|
24
|
+
function decodeCombinedRepairCursorForContract(rawCursor, keyring, wire) {
|
|
25
|
+
if (wire.taskCoverProjectionRequired)
|
|
26
|
+
return decodeWorkspaceSyncV3TaskCoverRepairCursor(rawCursor, keyring);
|
|
27
|
+
if (wire.workflowWriterPrerequisitesRequired)
|
|
28
|
+
return decodeWorkspaceSyncV3WorkflowRepairCursor(rawCursor, keyring);
|
|
29
|
+
if (wire.planningOrderWriterPrerequisitesRequired)
|
|
30
|
+
return decodeWorkspaceSyncV3PlanningOrderRepairCursor(rawCursor, keyring);
|
|
31
|
+
if (wire.nestedWriterPrerequisitesRequired)
|
|
32
|
+
return decodeWorkspaceSyncV3NestedRepairCursor(rawCursor, keyring);
|
|
33
|
+
return decodeWorkspaceSyncV3CombinedRepairCursor(rawCursor, keyring);
|
|
34
|
+
}
|
|
24
35
|
function attestLegacyPushBoundary(body, boundary) {
|
|
25
36
|
const attested = { ...body, ...boundary };
|
|
26
37
|
const mutable = attested;
|
|
@@ -215,13 +226,7 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
215
226
|
return;
|
|
216
227
|
}
|
|
217
228
|
const rawCursor = String(url.searchParams.get('cursor') || '').trim();
|
|
218
|
-
const cursor = requestedWire
|
|
219
|
-
? decodeWorkspaceSyncV3WorkflowRepairCursor(rawCursor, keyring)
|
|
220
|
-
: requestedWire.planningOrderWriterPrerequisitesRequired
|
|
221
|
-
? decodeWorkspaceSyncV3PlanningOrderRepairCursor(rawCursor, keyring)
|
|
222
|
-
: requestedWire.nestedWriterPrerequisitesRequired
|
|
223
|
-
? decodeWorkspaceSyncV3NestedRepairCursor(rawCursor, keyring)
|
|
224
|
-
: decodeWorkspaceSyncV3CombinedRepairCursor(rawCursor, keyring);
|
|
229
|
+
const cursor = decodeCombinedRepairCursorForContract(rawCursor, keyring, requestedWire);
|
|
225
230
|
if (rawCursor && !cursor) {
|
|
226
231
|
json(res, 400, { success: false, code: 'INVALID_SYNC_COMBINED_REPAIR_CURSOR', error: 'Invalid combined repair cursor.' });
|
|
227
232
|
return;
|
|
@@ -231,7 +236,8 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
231
236
|
cursorKeyring: keyring, cursor, pageSize: Number.isFinite(limit) ? limit : undefined,
|
|
232
237
|
nestedCoverage: requestedWire.nestedWriterPrerequisitesRequired,
|
|
233
238
|
workflowCoverage: requestedWire.workflowWriterPrerequisitesRequired,
|
|
234
|
-
planningOrderCoverage: requestedWire.planningOrderWriterPrerequisitesRequired
|
|
239
|
+
planningOrderCoverage: requestedWire.planningOrderWriterPrerequisitesRequired,
|
|
240
|
+
taskCoverCoverage: requestedWire.taskCoverProjectionRequired });
|
|
235
241
|
json(res, 200, attestLegacyPushBoundary({ ...page }, {
|
|
236
242
|
contractVersion: 3,
|
|
237
243
|
legacyV2Boundary: { cloudWritesFenced: false, excludedProjections: [] },
|
|
@@ -328,13 +334,7 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
328
334
|
return;
|
|
329
335
|
}
|
|
330
336
|
const repairCursor = coverage.kind === 'combined'
|
|
331
|
-
? (coverage.wire
|
|
332
|
-
? decodeWorkspaceSyncV3WorkflowRepairCursor(rawRepairCursor, cursorKeyring)
|
|
333
|
-
: coverage.wire.planningOrderWriterPrerequisitesRequired
|
|
334
|
-
? decodeWorkspaceSyncV3PlanningOrderRepairCursor(rawRepairCursor, cursorKeyring)
|
|
335
|
-
: coverage.wire.nestedWriterPrerequisitesRequired
|
|
336
|
-
? decodeWorkspaceSyncV3NestedRepairCursor(rawRepairCursor, cursorKeyring)
|
|
337
|
-
: decodeWorkspaceSyncV3CombinedRepairCursor(rawRepairCursor, cursorKeyring))
|
|
337
|
+
? decodeCombinedRepairCursorForContract(rawRepairCursor, cursorKeyring, coverage.wire)
|
|
338
338
|
: decodeWorkspaceSyncV3InitiativeRepairCursor(rawRepairCursor, cursorKeyring);
|
|
339
339
|
if (rawRepairCursor && (!repairEnabled || !repairCursor)) {
|
|
340
340
|
json(res, 400, { success: false, code: 'INVALID_SYNC_V3_REPAIR_CURSOR', error: 'Invalid repair cursor.' });
|
|
@@ -352,7 +352,9 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
352
352
|
pageSize: Number.isFinite(limit) ? limit : undefined,
|
|
353
353
|
nestedCoverage: coverage.wire.nestedWriterPrerequisitesRequired,
|
|
354
354
|
workflowCoverage: coverage.wire.workflowWriterPrerequisitesRequired,
|
|
355
|
-
planningOrderCoverage: coverage.wire.planningOrderWriterPrerequisitesRequired
|
|
355
|
+
planningOrderCoverage: coverage.wire.planningOrderWriterPrerequisitesRequired,
|
|
356
|
+
taskCoverCoverage: coverage.wire.taskCoverProjectionRequired,
|
|
357
|
+
coveredLegacyWritesFenced: combinedLegacyPushDisabled })
|
|
356
358
|
: buildWorkspaceSyncV3InitiativeRepairPage({ core: input.core, workspaceId,
|
|
357
359
|
cursorKeyring: cursorKeyring, cursor: repairCursor,
|
|
358
360
|
pageSize: Number.isFinite(limit) ? limit : undefined });
|
|
@@ -397,7 +399,9 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
397
399
|
cursorKeyring: cursorKeyring, pageSize: Number.isFinite(limit) ? limit : undefined,
|
|
398
400
|
nestedCoverage: coverage.wire.nestedWriterPrerequisitesRequired,
|
|
399
401
|
workflowCoverage: coverage.wire.workflowWriterPrerequisitesRequired,
|
|
400
|
-
planningOrderCoverage: coverage.wire.planningOrderWriterPrerequisitesRequired
|
|
402
|
+
planningOrderCoverage: coverage.wire.planningOrderWriterPrerequisitesRequired,
|
|
403
|
+
taskCoverCoverage: coverage.wire.taskCoverProjectionRequired,
|
|
404
|
+
coveredLegacyWritesFenced: combinedLegacyPushDisabled })
|
|
401
405
|
: buildWorkspaceSyncV3InitiativeRepairPage({ core: input.core, workspaceId,
|
|
402
406
|
cursorKeyring: cursorKeyring, pageSize: Number.isFinite(limit) ? limit : undefined });
|
|
403
407
|
const repair = coverage.kind === 'combined' ? page : { ...page,
|