@taskforcehq/taskforce 0.3.328 → 0.3.330
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 +523 -79
- 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/features/AiProfilesModule.js +3 -5
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +217 -54
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
- package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +5 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- 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/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- 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 +32 -55
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
- package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
- package/dist/config/envSchema.js +60 -1
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/McpTokenService.d.ts +23 -1
- package/dist/core/McpTokenService.js +93 -10
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/TaskChecklistCommandService.d.ts +27 -0
- package/dist/core/TaskChecklistCommandService.js +83 -5
- package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
- package/dist/core/TaskLifecycleCommandService.js +6 -2
- package/dist/core/Taskforce.d.ts +94 -2
- package/dist/core/Taskforce.js +760 -36
- package/dist/core/types.d.ts +14 -0
- package/dist/documentReviews/commandService.d.ts +2 -1
- package/dist/documentReviews/commandService.js +6 -3
- package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.js +2 -0
- 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/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
- package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
- package/dist/hooks/sync/useSyncStatusControls.js +47 -11
- 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 +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- 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/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +40 -1
- package/dist/hooks/useTaskData.js +240 -9
- package/dist/hooks/useTaskMutations.d.ts +12 -2
- package/dist/hooks/useTaskMutations.js +266 -52
- package/dist/hooks/useTaskforce.d.ts +39 -9
- package/dist/hooks/useTaskforce.js +359 -40
- 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/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +53 -41
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
- package/dist/mcp/durableTaskMutationRouter.js +10 -0
- package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
- package/dist/mcp/httpProtocolRouting.d.ts +10 -0
- package/dist/mcp/httpProtocolRouting.js +19 -0
- package/dist/mcp/localCliHealth.d.ts +2 -2
- package/dist/mcp/localCliHealth.js +2 -2
- package/dist/mcp/localServiceProxy.d.ts +1 -0
- package/dist/mcp/localServiceProxy.js +530 -68
- package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
- package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
- package/dist/mcp/runtime.d.ts +54 -79
- package/dist/mcp/runtime.js +556 -139
- package/dist/mcp/taskPlanningRegistrar.js +64 -42
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +10 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +1 -0
- package/dist/mcp/workflowExecutionRegistrar.js +4 -4
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +427 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +13 -13
- package/dist/runtime/appGates.js +36 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.js +123 -14
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +11 -2
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
- 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.d.ts +4 -0
- package/dist/server/routes/admin.js +113 -3
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +394 -39
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
- package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
- package/dist/server/routes/executorPhaseAApprovals.js +140 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
- package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
- package/dist/server/routes/githubReviewEvidence.js +116 -0
- package/dist/server/routes/localService.d.ts +15 -4
- package/dist/server/routes/localService.js +138 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/shared.d.ts +19 -0
- package/dist/server/routes/shared.js +95 -19
- package/dist/server/routes/sync.js +1 -0
- package/dist/server/routes/syncAuxRoutes.js +9 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +27 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +45 -9
- package/dist/server/routes/tasks.js +124 -13
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/routes.js +59 -0
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +161 -0
- package/dist/services/codexAppServerModelGateway.js +663 -0
- package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
- package/dist/services/codexDeviceCodeLoginManager.js +265 -0
- package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
- package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
- package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
- package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
- package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
- package/dist/services/executorPhaseAApprovalService.js +609 -0
- package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
- package/dist/services/executorPhaseADriftEvaluator.js +93 -0
- package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
- package/dist/services/executorPhaseAIssuerCore.js +295 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
- package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
- package/dist/services/githubReviewEvidenceRuntime.js +30 -0
- package/dist/services/githubReviewEvidenceService.d.ts +93 -0
- package/dist/services/githubReviewEvidenceService.js +336 -0
- package/dist/services/modelGateway.d.ts +7 -0
- package/dist/services/modelProviderConnectionService.d.ts +71 -0
- package/dist/services/modelProviderConnectionService.js +279 -0
- package/dist/services/modelProviderCredentialHome.d.ts +32 -0
- package/dist/services/modelProviderCredentialHome.js +271 -0
- package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
- package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
- package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
- package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
- package/dist/services/taskforceAgentMcpBridge.js +30 -27
- package/dist/shared/adminEdgeProxy.d.ts +5 -0
- package/dist/shared/adminEdgeProxy.js +94 -0
- package/dist/shared/adminProxySessionCookies.d.ts +16 -0
- package/dist/shared/adminProxySessionCookies.js +86 -0
- package/dist/shared/aiProfileColors.d.ts +31 -1
- package/dist/shared/aiProfileColors.js +14 -6
- package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
- package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
- package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
- package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
- package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
- package/dist/shared/executorPhaseADriftContracts.js +63 -0
- package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
- package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
- package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
- package/dist/shared/executorPhaseARunAuthorization.js +232 -0
- package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
- package/dist/shared/executorPhaseASchemaValidation.js +53 -0
- package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
- package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
- package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
- package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
- package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
- package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
- package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
- package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
- package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
- package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
- package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
- package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
- package/dist/shared/executorPhaseATiming.d.ts +1 -0
- package/dist/shared/executorPhaseATiming.js +1 -0
- package/dist/shared/planningIdentity.js +1 -1
- package/dist/shared/productLogoKeys.d.ts +2 -0
- package/dist/shared/productLogoKeys.js +18 -0
- package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
- package/dist/shared/taskforceAgentDefinition.js +6 -3
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +36 -3
- package/dist/shared/userFeatureGrants.d.ts +4 -0
- package/dist/shared/userFeatureGrants.js +7 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
- package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
- package/dist/storage/modelProviderConnectionStore.js +446 -0
- package/dist/storage/postgresAdapter.d.ts +24 -3
- package/dist/storage/postgresAdapter.js +117 -14
- package/dist/storage/postgresWorker.js +22 -5
- package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -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 +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
- package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
- package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
- package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
- package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
- package/dist/sync/syncApplyHandlers.d.ts +2 -0
- package/dist/sync/syncApplyHandlers.js +10 -1
- package/dist/sync/syncService.d.ts +17 -0
- package/dist/sync/syncService.js +87 -19
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +8 -0
- package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
- package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
- package/dist/sync/v3/durableOperationReplay.js +18 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
- package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
- package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
- package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
- package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
- package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
- package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
- 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 +10 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
- package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
- package/dist/sync/v3/syncDurabilityStore.js +199 -13
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
- package/dist/sync/v3/taskChecklistMutationService.js +48 -1
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- 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 +31 -1
- package/dist/sync/v3/taskStatusMutationService.js +123 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
- package/dist/sync/v3/workflowAssignmentSync.js +30 -0
- package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
- package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
- package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- 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.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -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 +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -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/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +8 -2
- package/dist/sync/workspaceRepair.js +222 -6
- package/dist/sync/workspaceSyncModel.d.ts +21 -0
- package/dist/sync/workspaceSyncModel.js +35 -7
- package/dist/sync/workspaceSyncState.d.ts +1 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
- package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
- package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
- package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
- package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
- package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-CTsDBaef.js +7 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
- package/dist/ui/branding/logos/letterhead_dark.png +0 -0
- package/dist/ui/branding/logos/letterhead_light.png +0 -0
- package/dist/ui/branding/logos/signature_dark.png +0 -0
- package/dist/ui/branding/logos/signature_light.png +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/aiProfileDefaultLogo.js +16 -48
- package/dist/utils/httpSetCookie.d.ts +1 -0
- package/dist/utils/httpSetCookie.js +4 -1
- package/dist/utils/localRuntimeUrl.d.ts +1 -0
- package/dist/utils/localRuntimeUrl.js +14 -0
- package/dist/utils/productLogoRegistry.d.ts +2 -0
- package/dist/utils/productLogoRegistry.js +36 -0
- package/dist/utils/syncStatusPresentation.d.ts +4 -0
- package/dist/utils/syncStatusPresentation.js +17 -0
- 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/taskEvents.d.ts +2 -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/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +36 -6
- package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
-
import { AlertTriangle, ChevronDown, Copy, Loader2
|
|
3
|
+
import { AlertTriangle, ChevronDown, Copy, Loader2 } from 'lucide-react';
|
|
4
4
|
import { Modal } from '../../../ui/Modal';
|
|
5
5
|
import modalStyles from '../../../ui/Modal.module.css';
|
|
6
6
|
import syncStatusStyles from '../../SyncStatusModal.module.css';
|
|
7
7
|
import styles from '../../../../Taskforce.module.css';
|
|
8
8
|
import { isWorkspaceSyncAuthenticationError } from '../../../../utils/workspaceSyncPresentation';
|
|
9
|
-
export function SyncStatusModal({ isOpen, theme, currentWorkspaceLabel, syncStatus, syncStatusMeta, workspaceCloudSyncEnabled, syncControlBusy, canManageWorkspaceSync, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncRepairBusy, referenceMismatchCount, syncStageLabel, workspaceSyncPendingChanges, incomingCloudChanges, formattedLastSyncTime, formattedLastPullTime, formattedLastPushTime, syncLastError, activeReferenceMismatchSummaries, syncDiagnosticsSummary, syncEventRows, syncEventsListRef, workspaceSyncRepairQueued, workspaceSyncBusy, workspaceSyncCopied, coordinatorOwnershipMode, coordinatorOwnershipTransferBusy, coordinatorOwnershipTransferDisabled, onClose, onToggleWorkspaceSync, onRepairSync, onCopyReport,
|
|
9
|
+
export function SyncStatusModal({ isOpen, theme, currentWorkspaceLabel, syncStatus, syncStatusMeta, workspaceCloudSyncEnabled, syncControlBusy, syncControlIntent, canManageWorkspaceSync, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncRepairBusy, referenceMismatchCount, syncStageLabel, workspaceSyncPendingChanges, incomingCloudChanges, formattedLastSyncTime, formattedLastPullTime, formattedLastPushTime, syncLastError, activeReferenceMismatchSummaries, syncDiagnosticsSummary, syncEventRows, syncEventsListRef, workspaceSyncRepairQueued, workspaceSyncBusy, workspaceSyncCopied, coordinatorOwnershipMode, coordinatorOwnershipTransferBusy, coordinatorOwnershipTransferDisabled, onClose, onToggleWorkspaceSync, onRepairSync, onCopyReport, onTransferCoordinatorOwnership, }) {
|
|
10
10
|
const [eventFilter, setEventFilter] = useState('all');
|
|
11
11
|
useEffect(() => {
|
|
12
12
|
if (isOpen)
|
|
13
13
|
setEventFilter('all');
|
|
14
14
|
}, [isOpen]);
|
|
15
15
|
const needsAttention = syncStatus === 'attention';
|
|
16
|
+
const displayedSyncEnabled = syncControlIntent === 'enabling'
|
|
17
|
+
? true
|
|
18
|
+
: syncControlIntent === 'disabling'
|
|
19
|
+
? false
|
|
20
|
+
: workspaceCloudSyncEnabled;
|
|
21
|
+
const syncControlTransitionLabel = syncControlIntent === 'enabling'
|
|
22
|
+
? 'Turning on…'
|
|
23
|
+
: syncControlIntent === 'disabling'
|
|
24
|
+
? 'Turning off…'
|
|
25
|
+
: null;
|
|
16
26
|
const activeIssue = workspaceSyncRepairBusy
|
|
17
27
|
? referenceMismatchCount > 0
|
|
18
28
|
? `Repair is reconciling cloud state, including ${referenceMismatchCount} reference mismatch${referenceMismatchCount === 1 ? '' : 'es'}.`
|
|
@@ -26,58 +36,43 @@ export function SyncStatusModal({ isOpen, theme, currentWorkspaceLabel, syncStat
|
|
|
26
36
|
const coordinatorOwnedByOtherProcess = /\banother local taskforce process owns workspace synchronization\b/i.test(syncLastError);
|
|
27
37
|
const coordinatorAuthenticationRequired = isWorkspaceSyncAuthenticationError(syncLastError);
|
|
28
38
|
const repairActionAvailable = workspaceCloudSyncEnabled
|
|
39
|
+
&& syncStatus !== 'checking'
|
|
29
40
|
&& !coordinatorOwnedByOtherProcess
|
|
30
41
|
&& !coordinatorAuthenticationRequired
|
|
31
42
|
&& (needsAttention
|
|
32
43
|
|| workspaceSyncBusy
|
|
33
44
|
|| workspaceSyncRepairBusy
|
|
34
45
|
|| workspaceSyncRepairQueued);
|
|
35
|
-
const retryActionAvailable = workspaceCloudSyncEnabled
|
|
36
|
-
&& !coordinatorOwnedByOtherProcess
|
|
37
|
-
&& !coordinatorAuthenticationRequired
|
|
38
|
-
&& (workspaceSyncBusy
|
|
39
|
-
|| needsAttention
|
|
40
|
-
|| /\bpress sync\b/i.test(workspaceSyncRecommendedAction));
|
|
41
46
|
const visibleEventRows = useMemo(() => eventFilter === 'issues'
|
|
42
47
|
? syncEventRows.filter((row) => row.tone === 'error')
|
|
43
48
|
: syncEventRows, [eventFilter, syncEventRows]);
|
|
44
|
-
const footer = (_jsxs("div", { className: syncStatusStyles.syncStatusFooter, children: [_jsxs("button", { className: styles.cancelBtn, onClick: onCopyReport, title: "Copy the current sync manager report for support or AI troubleshooting.", children: [_jsx(Copy, { size: 14 }), _jsx("span", { children: workspaceSyncCopied ? 'Copied' : 'Copy Report' })] }),
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
: !workspaceCloudSyncEnabled
|
|
51
|
-
? 'Turn on workspace sync before running Repair.'
|
|
52
|
-
: coordinatorOwnedByOtherProcess
|
|
53
|
-
? 'Repair is unavailable in this process. Use the Taskforce process that owns workspace synchronization.'
|
|
54
|
-
: coordinatorAuthenticationRequired
|
|
55
|
-
? 'Sign out and sign back in before running Repair.'
|
|
56
|
-
: workspaceSyncBusy
|
|
57
|
-
? 'Queue a repair to start automatically when the current sync finishes.'
|
|
58
|
-
: !repairActionAvailable
|
|
59
|
-
? 'Repair is available when sync needs attention.'
|
|
60
|
-
: 'Advanced recovery: clear the saved pull cursor and re-fetch cloud state from the beginning.', children: workspaceSyncRepairBusy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 14, className: styles.spinner }), "Repairing..."] })) : workspaceSyncRepairQueued ? ('Repair Queued') : ('Repair') }), _jsx("button", { className: styles.submitBtn, onClick: onRetrySync, disabled: !retryActionAvailable || workspaceSyncBusy, title: workspaceSyncBusy
|
|
61
|
-
? 'A sync request is already running.'
|
|
49
|
+
const footer = (_jsxs("div", { className: syncStatusStyles.syncStatusFooter, children: [_jsxs("button", { className: styles.cancelBtn, onClick: onCopyReport, title: "Copy the current sync manager report for support or AI troubleshooting.", children: [_jsx(Copy, { size: 14 }), _jsx("span", { children: workspaceSyncCopied ? 'Copied' : 'Copy Report' })] }), _jsx("div", { className: syncStatusStyles.syncStatusFooterPrimary, children: _jsx("button", { className: styles.cancelBtn, onClick: onRepairSync, disabled: !repairActionAvailable
|
|
50
|
+
|| workspaceSyncRepairBusy
|
|
51
|
+
|| workspaceSyncRepairQueued, title: workspaceSyncRepairBusy
|
|
52
|
+
? 'Repair is running now.'
|
|
53
|
+
: workspaceSyncRepairQueued
|
|
54
|
+
? 'Repair is queued and will start when the current sync finishes.'
|
|
62
55
|
: !workspaceCloudSyncEnabled
|
|
63
|
-
? 'Turn on workspace sync before
|
|
56
|
+
? 'Turn on workspace sync before running Repair.'
|
|
64
57
|
: coordinatorOwnedByOtherProcess
|
|
65
|
-
? '
|
|
58
|
+
? 'Repair is unavailable in this process. Use the Taskforce process that owns workspace synchronization.'
|
|
66
59
|
: coordinatorAuthenticationRequired
|
|
67
|
-
? 'Sign out and sign back in before
|
|
68
|
-
:
|
|
69
|
-
? '
|
|
70
|
-
:
|
|
60
|
+
? 'Sign out and sign back in before running Repair.'
|
|
61
|
+
: workspaceSyncBusy
|
|
62
|
+
? 'Queue a repair to start automatically when the current sync finishes.'
|
|
63
|
+
: !repairActionAvailable
|
|
64
|
+
? 'Repair is available when sync needs attention.'
|
|
65
|
+
: 'Advanced recovery: clear the saved pull cursor and re-fetch cloud state from the beginning.', children: workspaceSyncRepairBusy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 14, className: styles.spinner }), "Repairing..."] })) : workspaceSyncRepairQueued ? ('Repair Queued') : ('Repair') }) })] }));
|
|
71
66
|
return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: "Sync Manager", size: "mdWide", theme: theme, draggable: true, className: syncStatusStyles.syncStatusOverlay, footer: footer, children: _jsxs("div", { className: `${modalStyles.form} ${syncStatusStyles.syncStatusModal}`, children: [_jsxs("div", { className: syncStatusStyles.syncStatusTop, children: [_jsxs("div", { className: syncStatusStyles.syncStatusMetaHeader, children: [_jsx("div", { className: syncStatusStyles.syncStatusBadge, style: {
|
|
72
67
|
borderColor: syncStatusMeta.border,
|
|
73
68
|
background: syncStatusMeta.background,
|
|
74
69
|
color: syncStatusMeta.color
|
|
75
|
-
}, children: syncStatusMeta.label }), _jsxs("span", { className: syncStatusStyles.syncStatusLabel, children: ["Workspace: ", _jsx("code", { children: currentWorkspaceLabel })] })] }),
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
}, children: syncStatusMeta.label }), _jsxs("span", { className: syncStatusStyles.syncStatusLabel, children: ["Workspace: ", _jsx("code", { children: currentWorkspaceLabel })] })] }), _jsxs("label", { className: syncStatusStyles.syncToggle, children: [syncControlTransitionLabel ? (_jsx("span", { className: syncStatusStyles.syncToggleTransition, "aria-live": "polite", children: syncControlTransitionLabel })) : null, _jsxs("span", { className: [
|
|
71
|
+
syncStatusStyles.syncToggleControl,
|
|
72
|
+
displayedSyncEnabled ? syncStatusStyles.syncToggleControlEnabled : syncStatusStyles.syncToggleControlDisabled,
|
|
73
|
+
syncControlBusy ? syncStatusStyles.syncToggleControlBusy : '',
|
|
74
|
+
!canManageWorkspaceSync ? syncStatusStyles.syncToggleControlBlocked : ''
|
|
75
|
+
].filter(Boolean).join(' '), children: [_jsx("input", { className: syncStatusStyles.syncToggleInput, type: "checkbox", role: "switch", "aria-label": syncControlTransitionLabel || 'Enable Sync', checked: displayedSyncEnabled, disabled: !canManageWorkspaceSync || syncControlBusy, onChange: (event) => onToggleWorkspaceSync(event.target.checked) }), _jsx("span", { className: `${syncStatusStyles.syncToggleState} ${syncStatusStyles.syncToggleStateOn}`, children: "On" }), _jsx("span", { className: `${syncStatusStyles.syncToggleState} ${syncStatusStyles.syncToggleStateOff}`, children: "Off" }), _jsx("span", { className: syncStatusStyles.syncToggleThumb })] })] })] }), _jsxs("section", { className: syncStatusStyles.syncStatusOverview, "aria-label": "Sync status", children: [_jsxs("div", { className: syncStatusStyles.syncStatusOverviewRow, children: [_jsx("span", { className: syncStatusStyles.syncStatusLabel, children: "Health" }), _jsx("span", { className: syncStatusStyles.syncStatusSummaryValue, children: workspaceSyncSummary })] }), _jsxs("div", { className: syncStatusStyles.syncStatusOverviewRow, children: [_jsx("span", { className: syncStatusStyles.syncStatusLabel, children: "Next step" }), _jsx("span", { className: syncStatusStyles.syncStatusSummaryValue, children: workspaceSyncRecommendedAction })] }), _jsxs("div", { className: [
|
|
81
76
|
syncStatusStyles.syncStatusOverviewRow,
|
|
82
77
|
syncStatusStyles.syncStatusIssueRow,
|
|
83
78
|
activeIssueIsError ? syncStatusStyles.syncStatusIssueRowError : '',
|
package/dist/config/envSchema.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveDeploymentConfig } from './deployment.js';
|
|
2
2
|
import { MIGRATION_COMPAT_ENABLED } from '../runtime/migrationFlags.js';
|
|
3
3
|
import { parseWorkspaceSyncV3FeedCursorKeyring } from '../sync/v3/workspaceSyncV3FeedCursorKeys.js';
|
|
4
|
+
import { resolveExecutorPhaseAApprovalSigningConfig } from '../services/executorPhaseAApprovalService.js';
|
|
4
5
|
const SPECS = [
|
|
5
6
|
{ key: 'PORT', description: 'Standalone server port.', category: 'Core', defaultValue: '8080', targets: ['server', 'all'] },
|
|
6
7
|
{ key: 'TASKFORCE_TENANT_ID', description: 'Tenant identifier.', category: 'Core', defaultValue: 'default', targets: ['server', 'all'] },
|
|
@@ -66,7 +67,7 @@ const SPECS = [
|
|
|
66
67
|
{ key: 'TASKFORCE_SYNC_V3_LOCAL_FEED_APPLY_ENABLED', description: 'Enable the local-only atomic v3 initiative feed apply boundary.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
67
68
|
{ key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_ENABLED', description: 'Expose registered task-planning-metadata cloud feed and repair contracts.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
68
69
|
{ key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_ACTIVATION_ENABLED', description: 'Request combined coordinator activation; activation still requires exact local prerequisites and a matching ready cloud capability attestation.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
69
|
-
{ key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION', description: 'Request a frozen combined-feed coverage profile by registered version. Omit for version 3; version 4 adds nested task and entity-event coverage; version 5 adds workflow runtime coverage; version 6
|
|
70
|
+
{ key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION', description: 'Request a frozen combined-feed coverage profile by registered version. Omit for version 3; version 4 adds nested task and entity-event coverage; version 5 adds workflow runtime coverage; version 6 adds workstream task order; version 7 adds explicit task card covers; version 8 composes workflow runtime with version 7.', category: 'Core', defaultValue: '3', targets: ['server', 'all'] },
|
|
70
71
|
{ key: 'TASKFORCE_SYNC_V3_COMBINED_LOCAL_FEED_APPLY_ENABLED', description: 'Enable local atomic apply for registered task-planning-metadata coverage profiles.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
71
72
|
{ key: 'TASKFORCE_SYNC_V3_COMBINED_LEGACY_FENCE_ENABLED', description: 'Configure the combined stale-v2 fence; it becomes effective only after every covered cloud HTTP and MCP writer boundary is ready.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
72
73
|
{ key: 'TASKFORCE_SYNC_V3_NESTED_LEGACY_FENCE_ENABLED', description: 'Fence the four v4-only legacy projections after every nested cloud writer boundary is ready.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
@@ -75,6 +76,7 @@ const SPECS = [
|
|
|
75
76
|
{ key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_DISPATCH_ENABLED', description: 'Enable local durable workflow runtime outbox dispatch when the shared dispatcher is enabled.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
76
77
|
{ key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_HTTP_ACTIVATION_ENABLED', description: 'Route workflow runtime HTTP commands through durable v3 acceptance or local capture.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
77
78
|
{ key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_MCP_ACTIVATION_ENABLED', description: 'Route workflow runtime MCP commands through durable v3 acceptance or local capture.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
79
|
+
{ key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_MUTATIONS_FENCED', description: 'Temporarily reject workflow execution mutations during projection rollback.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
78
80
|
{ key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_CARRIER_COEXISTENCE_ENABLED', description: 'Acknowledge that task-status workflow activation remains the v5 bootstrap and rollback carrier.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
79
81
|
{ key: 'TASKFORCE_SYNC_V3_WORKSTREAM_TASK_ORDER_ENABLED', description: 'Enable cloud acceptance for durable v3 workstream task-order operations.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
80
82
|
{ key: 'TASKFORCE_SYNC_V3_WORKSTREAM_TASK_ORDER_CAPTURE_ENABLED', description: 'Enable local durable workstream task-order capture when the shared local capture and dispatch boundaries are enabled.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
@@ -89,6 +91,10 @@ const SPECS = [
|
|
|
89
91
|
{ key: 'TASKFORCE_AUTH_EXCLUDED_PATHS', description: 'Comma-separated API paths excluded from auth checks.', category: 'Auth', defaultValue: '/api/taskforce/health,/api/taskforce/version,/api/taskforce/auth,/api/taskforce/public/pricing,/api/taskforce/public/site-config,/api/taskforce/public/site-config-script', targets: ['server', 'all'] },
|
|
90
92
|
{ key: 'TASKFORCE_AUTH_DEFAULT_ROLE', description: 'Default role for unauthenticated context (owner|admin|member|read-only).', category: 'Auth', defaultValue: 'member', targets: ['server', 'all'] },
|
|
91
93
|
{ key: 'TASKFORCE_AUTH_SESSION_COOKIE', description: 'Session cookie name.', category: 'Auth', defaultValue: 'taskforce_session', targets: ['server', 'all'] },
|
|
94
|
+
{ key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE', description: 'Upstream cloud session cookie name used by every admin proxy target unless overridden per environment.', category: 'Auth', defaultValue: 'taskforce_session', targets: ['server', 'all'] },
|
|
95
|
+
{ key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE_PRODUCTION', description: 'Optional Production upstream session cookie name override for the admin proxy.', category: 'Auth', targets: ['server', 'all'] },
|
|
96
|
+
{ key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE_STAGING', description: 'Optional Staging upstream session cookie name override for the admin proxy.', category: 'Auth', targets: ['server', 'all'] },
|
|
97
|
+
{ key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE_PERFORMANCE', description: 'Optional Performance upstream session cookie name override for the admin proxy.', category: 'Auth', targets: ['server', 'all'] },
|
|
92
98
|
{ key: 'TASKFORCE_AUTH_SESSION_SECRET', description: 'Session signing secret.', category: 'Auth', secret: true, targets: ['server', 'all'] },
|
|
93
99
|
{ key: 'TASKFORCE_AUTH_SESSION_TTL_SECONDS', description: 'Session max age in seconds.', category: 'Auth', defaultValue: '2592000', targets: ['server', 'all'] },
|
|
94
100
|
{ key: 'TASKFORCE_AUTH_SESSION_SAMESITE', description: 'SameSite policy (Lax|Strict|None).', category: 'Auth', defaultValue: 'None', targets: ['server', 'all'] },
|
|
@@ -143,10 +149,16 @@ const SPECS = [
|
|
|
143
149
|
{ key: 'TASKFORCE_BEDROCK_SMOKE_MAX_TOKENS', description: 'Maximum output tokens for live Bedrock smoke tests.', category: 'AI', defaultValue: '128', targets: ['server', 'all'] },
|
|
144
150
|
{ key: 'TASKFORCE_BEDROCK_MANTLE_MODEL_KEY', description: 'Optional model key for Bedrock Mantle smoke tests (openai.gpt-5-4|xai.grok-4-3).', category: 'AI', defaultValue: 'openai.gpt-5-4', targets: ['server', 'all'] },
|
|
145
151
|
{ key: 'TASKFORCE_BEDROCK_ENV_FILE', description: 'Optional env file path for the Bedrock smoke script.', category: 'AI', defaultValue: '.env.local', targets: ['server', 'all'] },
|
|
152
|
+
{ key: 'TASKFORCE_AGENT_SUBSCRIPTION_DEV_MODELS', description: 'Enable internal local-development-only Taskforce Agent subscription-auth model adapters such as OpenAI Codex app-server.', category: 'AI', defaultValue: 'false', targets: ['server', 'all'] },
|
|
153
|
+
{ key: 'TASKFORCE_CODEX_APP_SERVER_COMMAND', description: 'Optional Codex CLI command path for the internal OpenAI Codex app-server Taskforce Agent adapter.', category: 'AI', defaultValue: 'codex', targets: ['server', 'all'] },
|
|
154
|
+
{ key: 'TASKFORCE_CODEX_APP_SERVER_CWD', description: 'Optional working directory for the internal Codex app-server subprocess. Defaults to the system temp directory.', category: 'AI', targets: ['server', 'all'] },
|
|
155
|
+
{ key: 'TASKFORCE_MODEL_CONNECTION_STORAGE_PATH', description: 'Restricted durable volume root for isolated user-owned model provider credential homes.', category: 'AI', targets: ['server', 'all'] },
|
|
146
156
|
{ key: 'TASKFORCE_ALLOWED_ORIGINS', description: 'Allowed CORS origins (comma-separated).', category: 'Security', targets: ['server', 'all'] },
|
|
147
157
|
{ key: 'TASKFORCE_API_RATE_LIMIT_ENABLED', description: 'Enable API rate limiter.', category: 'Security', defaultValue: 'true', targets: ['server', 'all'] },
|
|
148
158
|
{ key: 'TASKFORCE_API_RATE_LIMIT_MAX_REQUESTS', description: 'API rate limit max requests per window.', category: 'Security', defaultValue: '120', targets: ['server', 'all'] },
|
|
149
159
|
{ key: 'TASKFORCE_API_RATE_LIMIT_WINDOW_MS', description: 'API rate limit window size in ms.', category: 'Security', defaultValue: '60000', targets: ['server', 'all'] },
|
|
160
|
+
{ key: 'TASKFORCE_SYNC_FEED_RATE_LIMIT_MAX_REQUESTS', description: 'Workspace sync feed read limit per window.', category: 'Security', defaultValue: '600', targets: ['server', 'all'] },
|
|
161
|
+
{ key: 'TASKFORCE_SYNC_FEED_RATE_LIMIT_WINDOW_MS', description: 'Workspace sync feed read limit window size in ms.', category: 'Security', defaultValue: '60000', targets: ['server', 'all'] },
|
|
150
162
|
{ key: 'TASKFORCE_STRIPE_WEBHOOK_RATE_LIMIT_MAX_REQUESTS', description: 'Stripe webhook-specific rate limit max requests per window.', category: 'Security', defaultValue: '600', targets: ['server', 'all'] },
|
|
151
163
|
{ key: 'TASKFORCE_STRIPE_WEBHOOK_RATE_LIMIT_WINDOW_MS', description: 'Stripe webhook-specific rate limit window size in ms.', category: 'Security', defaultValue: '60000', targets: ['server', 'all'] },
|
|
152
164
|
{ key: 'TASKFORCE_MAX_PAYLOAD_BYTES', description: 'Maximum accepted API payload size in bytes.', category: 'Security', defaultValue: '1048576', targets: ['server', 'all'] },
|
|
@@ -160,6 +172,12 @@ const SPECS = [
|
|
|
160
172
|
{ key: 'TASKFORCE_ADMIN_AUDIT_SYNC_RETENTION_DAYS', description: 'Retention period for non-routine sync audit failures and exceptional events.', category: 'Security', defaultValue: '30', targets: ['server', 'all'] },
|
|
161
173
|
{ key: 'TASKFORCE_ADMIN_AUDIT_RETENTION_DAYS', description: 'Default retention period for administrative and security audit events.', category: 'Security', defaultValue: '365', targets: ['server', 'all'] },
|
|
162
174
|
{ key: 'TASKFORCE_SYNC_KEY', description: 'Optional sync encryption key.', category: 'Security', secret: true, targets: ['server', 'all'] },
|
|
175
|
+
{ key: 'TASKFORCE_GITHUB_REVIEW_APP_ID', description: 'GitHub App identifier used for private-repository review evidence.', category: 'Security', targets: ['server', 'all'] },
|
|
176
|
+
{ key: 'TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64', description: 'Base64-encoded GitHub App private key used only to mint short-lived installation tokens.', category: 'Security', secret: true, targets: ['server', 'all'] },
|
|
177
|
+
{ key: 'TASKFORCE_PHASE_A_APPROVAL_ISSUER_ENABLED', description: 'Enable performance-cloud Phase A approval receipt issuance.', category: 'Security', defaultValue: 'false', targets: ['server', 'all'] },
|
|
178
|
+
{ key: 'TASKFORCE_PHASE_A_ISSUER_REDEMPTION_ENABLED', description: 'Expose the disabled performance-cloud Phase A issuer redemption boundary.', category: 'Security', defaultValue: 'false', targets: ['server', 'all'] },
|
|
179
|
+
{ key: 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_KEY_ID', description: 'Active source-pinned Ed25519 key ID for performance Phase A approval receipts.', category: 'Security', targets: ['server', 'all'] },
|
|
180
|
+
{ key: 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_PRIVATE_KEY_PKCS8_BASE64', description: 'Base64-encoded PKCS#8 Ed25519 private key for performance Phase A approval receipts.', category: 'Security', secret: true, targets: ['server', 'all'] },
|
|
163
181
|
{ key: 'TASKFORCE_STRIPE_SECRET_KEY', description: 'Stripe secret API key used by server-side billing routes.', category: 'Security', secret: true, targets: ['server', 'all'] },
|
|
164
182
|
{ key: 'TASKFORCE_STRIPE_WEBHOOK_SECRET', description: 'Stripe webhook signing secret used to verify incoming webhooks.', category: 'Security', secret: true, targets: ['server', 'all'] },
|
|
165
183
|
{ key: 'TASKFORCE_BUILD_VERSION', description: 'Build version metadata.', category: 'Build', targets: ['server', 'all'] },
|
|
@@ -168,6 +186,8 @@ const SPECS = [
|
|
|
168
186
|
{ key: 'TASKFORCE_BUILD_DEPLOY_ID', description: 'Build deploy ID metadata.', category: 'Build', targets: ['server', 'all'] },
|
|
169
187
|
{ key: 'TASKFORCE_UI_DIST_DIR', description: 'Override the standalone UI distribution directory for isolated local QA runtimes.', category: 'Build', targets: ['server', 'all'] },
|
|
170
188
|
{ key: 'TASKFORCE_REQUIRE_EXACT_PORT', description: 'Require the standalone server to use only its requested port.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
|
|
189
|
+
{ key: 'TASKFORCE_QA_EXPECTED_WORKSPACE_ID', description: 'Require isolated cloud QA to resolve the exact expected workspace ID before mutation.', category: 'Core', targets: ['server', 'all'] },
|
|
190
|
+
{ key: 'TASKFORCE_QA_EXPECTED_WORKSPACE_SLUG', description: 'Require isolated cloud QA to resolve the expected workspace slug before mutation.', category: 'Core', targets: ['server', 'all'] },
|
|
171
191
|
{ key: 'DEBUG_MODE', description: 'Expose debug-only client diagnostics such as pricing source metadata.', category: 'Build', defaultValue: 'false', targets: ['all'] },
|
|
172
192
|
{ key: 'VITE_TASKFORCE_BASE_URL', description: 'Client base URL for both API and cloud auth when specific overrides are not set.', category: 'Client', example: 'https://performance-app.taskforcehq.ai', targets: ['all'] },
|
|
173
193
|
{ key: 'VITE_TASKFORCE_API_BASE_URL', description: 'Client API base URL (overrides VITE_TASKFORCE_BASE_URL when set).', category: 'Client', example: 'https://performance-app.taskforcehq.ai', targets: ['all'] },
|
|
@@ -185,17 +205,22 @@ const SPECS = [
|
|
|
185
205
|
{ key: 'SYNC_SOAK_PROFILE', description: 'Soak profile (smoke|stress|overnight).', category: 'Soak', defaultValue: 'smoke', targets: ['soak', 'all'] },
|
|
186
206
|
{ key: 'SYNC_SOAK_DURATION_MIN', description: 'Soak duration in minutes.', category: 'Soak', defaultValue: '60', targets: ['soak', 'all'] },
|
|
187
207
|
{ key: 'SYNC_SOAK_SEED', description: 'Deterministic soak seed.', category: 'Soak', example: '4242', targets: ['soak', 'all'] },
|
|
208
|
+
{ key: 'SYNC_SOAK_TASK_ID_NAMESPACE', description: 'Optional per-run namespace for deterministic generated soak task IDs.', category: 'Soak', targets: ['soak', 'all'] },
|
|
188
209
|
{ key: 'SYNC_SOAK_ARTIFACT_DIR', description: 'Soak artifacts output directory.', category: 'Soak', defaultValue: '.taskforce/soak-artifacts', targets: ['soak', 'all'] },
|
|
189
210
|
{ key: 'SYNC_SOAK_ENABLE_SYNC_DEBUG', description: 'Enable sync debug diagnostics during soak.', category: 'Soak', defaultValue: 'false', targets: ['soak', 'all'] },
|
|
190
211
|
{ key: 'SYNC_SOAK_STRESS_ACTIONS', description: 'Stress action count.', category: 'Soak', defaultValue: '150', targets: ['soak', 'all'] },
|
|
191
212
|
{ key: 'SYNC_SOAK_STRESS_CHECKPOINT_INTERVAL', description: 'Stress checkpoint interval.', category: 'Soak', defaultValue: '50', targets: ['soak', 'all'] },
|
|
192
213
|
{ key: 'SYNC_SOAK_STRESS_SETTLE_RETRIES', description: 'Stress settle retry count.', category: 'Soak', defaultValue: '3', targets: ['soak', 'all'] },
|
|
193
214
|
{ key: 'SYNC_SOAK_STRESS_SETTLE_WAIT_MS', description: 'Stress settle wait time in ms.', category: 'Soak', defaultValue: '500', targets: ['soak', 'all'] },
|
|
215
|
+
{ key: 'SYNC_SOAK_STRESS_BOOTSTRAP_PUSH_SETTLE', description: 'Enable legacy bootstrap-push checkpoint settlement in stress and overnight profiles.', category: 'Soak', defaultValue: 'true', targets: ['soak', 'all'] },
|
|
194
216
|
{ key: 'SYNC_SOAK_STRESS_HARD_RESET_SETTLE', description: 'Enable hard reset settle path in stress.', category: 'Soak', defaultValue: 'true', targets: ['soak', 'all'] },
|
|
195
217
|
{ key: 'SYNC_SOAK_OVERNIGHT_ACTION_INTERVAL_MS', description: 'Overnight action pacing interval in ms.', category: 'Soak', defaultValue: '60000', targets: ['soak', 'all'] },
|
|
196
218
|
{ key: 'SYNC_SOAK_OVERNIGHT_CHECKPOINT_MIN', description: 'Overnight checkpoint interval in minutes.', category: 'Soak', defaultValue: '15', targets: ['soak', 'all'] },
|
|
197
219
|
{ key: 'SYNC_SOAK_OVERNIGHT_MAX_ACTIONS', description: 'Overnight hard cap on action count.', category: 'Soak', defaultValue: '10000', targets: ['soak', 'all'] },
|
|
198
220
|
{ key: 'SYNC_SOAK_OVERNIGHT_MIN_ACTIONS', description: 'Overnight minimum actions expected before pass.', category: 'Soak', defaultValue: '80', targets: ['soak', 'all'] },
|
|
221
|
+
{ key: 'SYNC_SOAK_OVERNIGHT_CLEAN_BASELINE_EVERY_ACTION', description: 'Require coordinator settlement before each accelerated overnight action.', category: 'Soak', defaultValue: 'false', targets: ['soak', 'all'] },
|
|
222
|
+
{ key: 'SYNC_SOAK_SERVER_FAULT_PROFILE', description: 'Deterministic server-owned sync transport fault profile (none|operation-response-loss-once).', category: 'Soak', defaultValue: 'none', targets: ['soak', 'all'] },
|
|
223
|
+
{ key: 'SYNC_SOAK_CLEAN_BASELINE_TIMEOUT_MS', description: 'Bounded wait for coordinator recovery and clean-baseline settlement.', category: 'Soak', defaultValue: '180000', targets: ['soak', 'all'] },
|
|
199
224
|
{ key: 'CF_ACCESS_CLIENT_ID', description: 'Cloudflare Access service token client id (soak).', category: 'Cloudflare', secret: true, targets: ['soak', 'all'] },
|
|
200
225
|
{ key: 'CF_ACCESS_CLIENT_SECRET', description: 'Cloudflare Access service token client secret (soak).', category: 'Cloudflare', secret: true, targets: ['soak', 'all'] }
|
|
201
226
|
];
|
|
@@ -255,6 +280,8 @@ function validateCommonNumbers(env, errors) {
|
|
|
255
280
|
'PORT',
|
|
256
281
|
'TASKFORCE_API_RATE_LIMIT_MAX_REQUESTS',
|
|
257
282
|
'TASKFORCE_API_RATE_LIMIT_WINDOW_MS',
|
|
283
|
+
'TASKFORCE_SYNC_FEED_RATE_LIMIT_MAX_REQUESTS',
|
|
284
|
+
'TASKFORCE_SYNC_FEED_RATE_LIMIT_WINDOW_MS',
|
|
258
285
|
'TASKFORCE_STRIPE_WEBHOOK_RATE_LIMIT_MAX_REQUESTS',
|
|
259
286
|
'TASKFORCE_STRIPE_WEBHOOK_RATE_LIMIT_WINDOW_MS',
|
|
260
287
|
'TASKFORCE_MAX_PAYLOAD_BYTES',
|
|
@@ -345,6 +372,38 @@ function validateServerEnv(env, errors, warnings) {
|
|
|
345
372
|
if (provider === 'postgres' && !hasValue(env, 'TASKFORCE_DATABASE_URL')) {
|
|
346
373
|
errors.push('TASKFORCE_DATABASE_URL is required when TASKFORCE_DB_PROVIDER=postgres.');
|
|
347
374
|
}
|
|
375
|
+
const hasGitHubReviewAppId = hasValue(env, 'TASKFORCE_GITHUB_REVIEW_APP_ID');
|
|
376
|
+
const hasGitHubReviewPrivateKey = hasValue(env, 'TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64');
|
|
377
|
+
if (hasGitHubReviewAppId !== hasGitHubReviewPrivateKey) {
|
|
378
|
+
errors.push('TASKFORCE_GITHUB_REVIEW_APP_ID and TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 must be configured together.');
|
|
379
|
+
}
|
|
380
|
+
if (hasGitHubReviewPrivateKey) {
|
|
381
|
+
const encoded = String(env.TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 || '').trim();
|
|
382
|
+
const decoded = Buffer.from(encoded, 'base64').toString('utf8');
|
|
383
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(encoded) || !decoded.includes('-----BEGIN') || !decoded.includes('PRIVATE KEY-----')) {
|
|
384
|
+
errors.push('TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 must contain a base64-encoded PEM private key.');
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const phaseAIssuerEnabled = parseBoolean(env.TASKFORCE_PHASE_A_APPROVAL_ISSUER_ENABLED) === true;
|
|
388
|
+
const phaseARedemptionEnabled = parseBoolean(env.TASKFORCE_PHASE_A_ISSUER_REDEMPTION_ENABLED) === true;
|
|
389
|
+
const hasPhaseAKeyId = hasValue(env, 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_KEY_ID');
|
|
390
|
+
const hasPhaseAPrivateKey = hasValue(env, 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_PRIVATE_KEY_PKCS8_BASE64');
|
|
391
|
+
if (phaseAIssuerEnabled || hasPhaseAKeyId || hasPhaseAPrivateKey) {
|
|
392
|
+
if (runtimeMode !== 'cloud' || deployment.cloudEnvironment !== 'performance') {
|
|
393
|
+
errors.push('Phase A approval receipt signing is allowed only in the performance cloud runtime.');
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (phaseARedemptionEnabled && (runtimeMode !== 'cloud' || deployment.cloudEnvironment !== 'performance')) {
|
|
397
|
+
errors.push('Phase A issuer redemption is allowed only in the performance cloud runtime.');
|
|
398
|
+
}
|
|
399
|
+
if (hasValue(env, 'TASKFORCE_PHASE_A_APPROVAL_ISSUER_ENABLED') || hasPhaseAKeyId || hasPhaseAPrivateKey) {
|
|
400
|
+
try {
|
|
401
|
+
resolveExecutorPhaseAApprovalSigningConfig(env);
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
errors.push(String(error?.message || error));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
348
407
|
if (billingEnabled && !hasValue(env, 'TASKFORCE_STRIPE_SECRET_KEY')) {
|
|
349
408
|
errors.push('TASKFORCE_STRIPE_SECRET_KEY is required when TASKFORCE_BILLING_ENABLED=true.');
|
|
350
409
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface LocalServiceRuntimeContract {
|
|
2
|
+
schemaVersion: 1;
|
|
3
|
+
fingerprint: string;
|
|
4
|
+
coverageVersion: number | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function hydrateSourceCheckoutServiceEnvironment(input: {
|
|
7
|
+
env: NodeJS.ProcessEnv;
|
|
8
|
+
projectRoot: string;
|
|
9
|
+
packageRoot: string;
|
|
10
|
+
}): string | null;
|
|
11
|
+
export declare function resolveLocalServiceRuntimeContract(env: NodeJS.ProcessEnv): LocalServiceRuntimeContract;
|
|
12
|
+
export declare function parseLocalServiceRuntimeContract(value: unknown): LocalServiceRuntimeContract | null;
|
|
13
|
+
export declare function localServiceRuntimeContractsEqual(left: LocalServiceRuntimeContract | null | undefined, right: LocalServiceRuntimeContract | null | undefined): boolean;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { parseTaskforceCloudEnvironment } from './cloudEnvironment.js';
|
|
5
|
+
const SERVICE_ENV_EXACT_KEYS = new Set([
|
|
6
|
+
'CF_ACCESS_CLIENT_ID',
|
|
7
|
+
'CF_ACCESS_CLIENT_SECRET',
|
|
8
|
+
'TASKFORCE_CF_ACCESS_CLIENT_ID',
|
|
9
|
+
'TASKFORCE_CF_ACCESS_CLIENT_SECRET',
|
|
10
|
+
'TASKFORCE_REALTIME_SYNC',
|
|
11
|
+
'TASKFORCE_RUNTIME_MODE',
|
|
12
|
+
]);
|
|
13
|
+
function isServiceEnvironmentKey(key) {
|
|
14
|
+
if (SERVICE_ENV_EXACT_KEYS.has(key))
|
|
15
|
+
return true;
|
|
16
|
+
if (key.startsWith('TASKFORCE_E2E_') || key.startsWith('TASKFORCE_PLAYWRIGHT_'))
|
|
17
|
+
return false;
|
|
18
|
+
return key.startsWith('TASKFORCE_SYNC_')
|
|
19
|
+
|| key.startsWith('TASKFORCE_LOCAL_SYNC_')
|
|
20
|
+
|| key.startsWith('VITE_TASKFORCE_');
|
|
21
|
+
}
|
|
22
|
+
function isContractKey(key) {
|
|
23
|
+
return key === 'TASKFORCE_RUNTIME_MODE'
|
|
24
|
+
|| key === 'TASKFORCE_REALTIME_SYNC'
|
|
25
|
+
|| key.startsWith('TASKFORCE_SYNC_')
|
|
26
|
+
|| key.startsWith('TASKFORCE_LOCAL_SYNC_');
|
|
27
|
+
}
|
|
28
|
+
function stripQuotes(value) {
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
if (trimmed.length >= 2) {
|
|
31
|
+
const first = trimmed[0];
|
|
32
|
+
const last = trimmed[trimmed.length - 1];
|
|
33
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
34
|
+
return trimmed.slice(1, -1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return trimmed;
|
|
38
|
+
}
|
|
39
|
+
function isInside(parent, child) {
|
|
40
|
+
const relative = path.relative(parent, child);
|
|
41
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
42
|
+
}
|
|
43
|
+
function loadTrustedEnvFile(filePath, packageRoot, loaded, visited) {
|
|
44
|
+
const resolved = fs.realpathSync(filePath);
|
|
45
|
+
if (!isInside(packageRoot, resolved) || !path.basename(resolved).startsWith('.env')) {
|
|
46
|
+
throw new Error('Taskforce source-checkout environment includes must remain trusted .env files inside the package root.');
|
|
47
|
+
}
|
|
48
|
+
if (visited.has(resolved))
|
|
49
|
+
return;
|
|
50
|
+
visited.add(resolved);
|
|
51
|
+
const lines = fs.readFileSync(resolved, 'utf8').split(/\r?\n/);
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
const trimmed = line.trim();
|
|
54
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
55
|
+
continue;
|
|
56
|
+
const include = trimmed.match(/^(?:\.|source)\s+([^\s]+)$/);
|
|
57
|
+
if (include) {
|
|
58
|
+
const includePath = path.resolve(path.dirname(resolved), stripQuotes(include[1]));
|
|
59
|
+
loadTrustedEnvFile(includePath, packageRoot, loaded, visited);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const normalized = trimmed.startsWith('export ') ? trimmed.slice(7).trim() : trimmed;
|
|
63
|
+
const separator = normalized.indexOf('=');
|
|
64
|
+
if (separator <= 0)
|
|
65
|
+
continue;
|
|
66
|
+
const key = normalized.slice(0, separator).trim();
|
|
67
|
+
if (!/^[A-Z][A-Z0-9_]*$/.test(key) || !isServiceEnvironmentKey(key))
|
|
68
|
+
continue;
|
|
69
|
+
loaded.set(key, stripQuotes(normalized.slice(separator + 1)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function hydrateSourceCheckoutServiceEnvironment(input) {
|
|
73
|
+
const projectRoot = fs.realpathSync(input.projectRoot);
|
|
74
|
+
const packageRoot = fs.realpathSync(input.packageRoot);
|
|
75
|
+
if (projectRoot !== packageRoot)
|
|
76
|
+
return null;
|
|
77
|
+
const environment = parseTaskforceCloudEnvironment(input.env.TASKFORCE_CLOUD_ENVIRONMENT);
|
|
78
|
+
if (environment !== 'performance' && environment !== 'staging')
|
|
79
|
+
return null;
|
|
80
|
+
const envFile = path.join(packageRoot, `.env.${environment}`);
|
|
81
|
+
if (!fs.existsSync(envFile))
|
|
82
|
+
return null;
|
|
83
|
+
const explicitKeys = new Set(Object.keys(input.env));
|
|
84
|
+
const loaded = new Map();
|
|
85
|
+
loadTrustedEnvFile(envFile, packageRoot, loaded, new Set());
|
|
86
|
+
for (const [key, value] of loaded) {
|
|
87
|
+
if (!explicitKeys.has(key))
|
|
88
|
+
input.env[key] = value;
|
|
89
|
+
}
|
|
90
|
+
return envFile;
|
|
91
|
+
}
|
|
92
|
+
export function resolveLocalServiceRuntimeContract(env) {
|
|
93
|
+
const effectiveEnv = {
|
|
94
|
+
...env,
|
|
95
|
+
TASKFORCE_RUNTIME_MODE: String(env.TASKFORCE_RUNTIME_MODE || 'local').trim().toLowerCase(),
|
|
96
|
+
};
|
|
97
|
+
const entries = Object.entries(effectiveEnv)
|
|
98
|
+
.filter(([key, value]) => isContractKey(key) && value !== undefined)
|
|
99
|
+
.map(([key, value]) => [key, String(value)])
|
|
100
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
101
|
+
const fingerprint = createHash('sha256')
|
|
102
|
+
.update(JSON.stringify(entries))
|
|
103
|
+
.digest('hex');
|
|
104
|
+
const rawCoverageVersion = Number.parseInt(String(env.TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION || ''), 10);
|
|
105
|
+
return {
|
|
106
|
+
schemaVersion: 1,
|
|
107
|
+
fingerprint,
|
|
108
|
+
coverageVersion: Number.isSafeInteger(rawCoverageVersion) && rawCoverageVersion > 0
|
|
109
|
+
? rawCoverageVersion
|
|
110
|
+
: null,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export function parseLocalServiceRuntimeContract(value) {
|
|
114
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
115
|
+
return null;
|
|
116
|
+
const record = value;
|
|
117
|
+
if (record.schemaVersion !== 1
|
|
118
|
+
|| typeof record.fingerprint !== 'string'
|
|
119
|
+
|| !/^[a-f0-9]{64}$/.test(record.fingerprint)
|
|
120
|
+
|| (record.coverageVersion !== null
|
|
121
|
+
&& (!Number.isSafeInteger(record.coverageVersion) || Number(record.coverageVersion) < 1))) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
schemaVersion: 1,
|
|
126
|
+
fingerprint: record.fingerprint,
|
|
127
|
+
coverageVersion: record.coverageVersion === null ? null : Number(record.coverageVersion),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export function localServiceRuntimeContractsEqual(left, right) {
|
|
131
|
+
return Boolean(left && right
|
|
132
|
+
&& left.schemaVersion === right.schemaVersion
|
|
133
|
+
&& left.fingerprint === right.fingerprint
|
|
134
|
+
&& left.coverageVersion === right.coverageVersion);
|
|
135
|
+
}
|
|
@@ -931,15 +931,27 @@ function reconcileSyncedAiProfileConnectionBindings(deps, workspaceId, profileId
|
|
|
931
931
|
.sort()
|
|
932
932
|
: [];
|
|
933
933
|
const clientId = String(connection.clientId || '').trim() || null;
|
|
934
|
-
|
|
935
|
-
|
|
934
|
+
// Credential-derived bindings are authentication state owned by the cloud
|
|
935
|
+
// runtime. Synced profile metadata must never create, remove, or reassign
|
|
936
|
+
// them; doing so would let a stale replica change write attribution.
|
|
937
|
+
const syncedBindingIds = bindingIds.filter((bindingId) => !isCredentialOwnedConnectionBindingId(bindingId));
|
|
938
|
+
if (syncedBindingIds.length === 0) {
|
|
939
|
+
deps.db.prepare(`DELETE FROM ai_profile_connection_bindings
|
|
940
|
+
WHERE tenant_id = ? AND workspace_id = ? AND profile_id = ?
|
|
941
|
+
AND connection_id NOT LIKE 'oauth:%'
|
|
942
|
+
AND connection_id NOT LIKE 'oauth-client:%'
|
|
943
|
+
AND connection_id NOT LIKE 'token:%'`)
|
|
936
944
|
.run(deps.tenantId, workspaceId, profileId);
|
|
937
945
|
return;
|
|
938
946
|
}
|
|
939
|
-
const placeholders =
|
|
947
|
+
const placeholders = syncedBindingIds.map(() => '?').join(', ');
|
|
940
948
|
deps.db.prepare(`DELETE FROM ai_profile_connection_bindings
|
|
941
|
-
WHERE tenant_id = ? AND workspace_id = ? AND profile_id = ?
|
|
942
|
-
|
|
949
|
+
WHERE tenant_id = ? AND workspace_id = ? AND profile_id = ?
|
|
950
|
+
AND connection_id NOT LIKE 'oauth:%'
|
|
951
|
+
AND connection_id NOT LIKE 'oauth-client:%'
|
|
952
|
+
AND connection_id NOT LIKE 'token:%'
|
|
953
|
+
AND connection_id NOT IN (${placeholders})`)
|
|
954
|
+
.run(deps.tenantId, workspaceId, profileId, ...syncedBindingIds);
|
|
943
955
|
const now = new Date().toISOString();
|
|
944
956
|
const upsert = deps.db.prepare(`INSERT INTO ai_profile_connection_bindings
|
|
945
957
|
(tenant_id, workspace_id, connection_id, profile_id, client_id, created_at, updated_at)
|
|
@@ -948,7 +960,7 @@ function reconcileSyncedAiProfileConnectionBindings(deps, workspaceId, profileId
|
|
|
948
960
|
profile_id = excluded.profile_id,
|
|
949
961
|
client_id = excluded.client_id,
|
|
950
962
|
updated_at = excluded.updated_at`);
|
|
951
|
-
for (const bindingId of
|
|
963
|
+
for (const bindingId of syncedBindingIds) {
|
|
952
964
|
upsert.run(deps.tenantId, workspaceId, bindingId, profileId, clientId, now, now);
|
|
953
965
|
}
|
|
954
966
|
}
|
|
@@ -1282,6 +1294,11 @@ function normalizeConnectionBindingId(deps, value) {
|
|
|
1282
1294
|
}
|
|
1283
1295
|
return normalized;
|
|
1284
1296
|
}
|
|
1297
|
+
function isCredentialOwnedConnectionBindingId(connectionId) {
|
|
1298
|
+
return connectionId.startsWith('oauth:')
|
|
1299
|
+
|| connectionId.startsWith('oauth-client:')
|
|
1300
|
+
|| connectionId.startsWith('token:');
|
|
1301
|
+
}
|
|
1285
1302
|
function parseProviderMetadataRow(row) {
|
|
1286
1303
|
if (typeof row.provider_metadata_json !== 'string' || !row.provider_metadata_json.trim())
|
|
1287
1304
|
return {};
|
|
@@ -1304,10 +1321,29 @@ export function bindAiProfileConnectionService(deps, input) {
|
|
|
1304
1321
|
if (!target)
|
|
1305
1322
|
throw deps.createRuleError(`Profile ${profileId} not found`, 404, 'AI_PROFILE_NOT_FOUND');
|
|
1306
1323
|
const now = new Date().toISOString();
|
|
1307
|
-
deps.db.prepare(`INSERT INTO ai_profile_connection_bindings
|
|
1324
|
+
deps.db.prepare(`INSERT INTO ai_profile_connection_bindings
|
|
1325
|
+
(tenant_id, workspace_id, connection_id, profile_id, client_id, created_at, updated_at)
|
|
1308
1326
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1309
|
-
ON CONFLICT (tenant_id, workspace_id, connection_id) DO
|
|
1327
|
+
ON CONFLICT (tenant_id, workspace_id, connection_id) DO NOTHING`)
|
|
1310
1328
|
.run(deps.tenantId, workspaceId, connectionId, profileId, clientId, now, now);
|
|
1329
|
+
const existing = deps.db.prepare(`SELECT b.profile_id, p.archived_at
|
|
1330
|
+
FROM ai_profile_connection_bindings b
|
|
1331
|
+
LEFT JOIN ai_profiles p ON p.tenant_id = b.tenant_id AND p.workspace_id = b.workspace_id AND p.id = b.profile_id
|
|
1332
|
+
WHERE b.tenant_id = ? AND b.workspace_id = ? AND b.connection_id = ? LIMIT 1`)
|
|
1333
|
+
.get(deps.tenantId, workspaceId, connectionId);
|
|
1334
|
+
if (!existing?.profile_id) {
|
|
1335
|
+
throw deps.createRuleError('Failed to establish the MCP connection binding.', 500, 'AI_PROFILE_CONNECTION_BIND_FAILED');
|
|
1336
|
+
}
|
|
1337
|
+
if (existing && existing.profile_id !== profileId && !existing.archived_at) {
|
|
1338
|
+
throw deps.createRuleError('This MCP connection is already bound to a different active AI profile. Reconnect or use an authorized profile recovery flow.', 409, 'AI_PROFILE_CONNECTION_CONFLICT', { workspaceId, connectionId, existingProfileId: existing.profile_id || null, requestedProfileId: profileId });
|
|
1339
|
+
}
|
|
1340
|
+
const updateResult = deps.db.prepare(`UPDATE ai_profile_connection_bindings
|
|
1341
|
+
SET profile_id = ?, client_id = ?, updated_at = ?
|
|
1342
|
+
WHERE tenant_id = ? AND workspace_id = ? AND connection_id = ? AND profile_id = ?`)
|
|
1343
|
+
.run(profileId, clientId, now, deps.tenantId, workspaceId, connectionId, existing.profile_id);
|
|
1344
|
+
if (updateResult.changes !== 1) {
|
|
1345
|
+
throw deps.createRuleError('The MCP connection binding changed concurrently. Retry after refreshing the intended profile.', 409, 'AI_PROFILE_CONNECTION_CONFLICT', { workspaceId, connectionId, expectedProfileId: existing.profile_id || null, requestedProfileId: profileId });
|
|
1346
|
+
}
|
|
1311
1347
|
const rows = deps.db.prepare(`SELECT * FROM ai_profiles WHERE tenant_id = ? AND workspace_id = ?`).all(deps.tenantId, workspaceId);
|
|
1312
1348
|
for (const row of rows) {
|
|
1313
1349
|
const metadata = parseProviderMetadataRow(row);
|
|
@@ -1351,6 +1387,8 @@ export function getAiProfileByConnectionService(deps, input) {
|
|
|
1351
1387
|
const record = hydrateAiProfileRecord(deps, binding);
|
|
1352
1388
|
return input.seatScope !== undefined && (record.seatScope ?? null) !== input.seatScope ? null : record;
|
|
1353
1389
|
}
|
|
1390
|
+
if (isCredentialOwnedConnectionBindingId(connectionId))
|
|
1391
|
+
return null;
|
|
1354
1392
|
const legacyRows = deps.db.prepare(`SELECT * FROM ai_profiles WHERE tenant_id = ? AND workspace_id = ?`).all(deps.tenantId, workspaceId)
|
|
1355
1393
|
.filter((row) => {
|
|
1356
1394
|
const record = hydrateAiProfileRecord(deps, row);
|
|
@@ -8,6 +8,7 @@ export interface DeletedTaskLifecycleServiceDeps {
|
|
|
8
8
|
generateEntityId: (prefix: string) => string;
|
|
9
9
|
normalizeWorkspaceId: (workspaceId: string | undefined) => string;
|
|
10
10
|
resolveWorkspaceActor: (workspaceId: string, actorRef: unknown) => TaskActor | null;
|
|
11
|
+
resolveWorkspaceActors: (workspaceId: string, actorRefs: unknown[]) => Map<string, TaskActor | null>;
|
|
11
12
|
sanitizeOrderInDay: (value: unknown) => number | null;
|
|
12
13
|
sanitizeDateOnly: (value: unknown) => string | null;
|
|
13
14
|
normalizeTaskEventActor: (actorRef: unknown, workspaceId: string) => {
|
|
@@ -119,6 +119,41 @@ export function mapDeletedTaskRowService(deps, row) {
|
|
|
119
119
|
actorProfile: actor === 'system' ? null : deps.resolveWorkspaceActor(workspaceId, actor)
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
+
function mapDeletedTaskRowsService(deps, rows) {
|
|
123
|
+
const actorProfiles = new Map();
|
|
124
|
+
const actorRefsByWorkspace = new Map();
|
|
125
|
+
for (const row of rows) {
|
|
126
|
+
const workspaceId = deps.normalizeWorkspaceId(typeof row.workspace_id === 'string' ? row.workspace_id : undefined);
|
|
127
|
+
const actorRef = String(row.actor || 'system').trim() || 'system';
|
|
128
|
+
if (actorRef === 'system') {
|
|
129
|
+
actorProfiles.set(`${workspaceId}\u0000${actorRef}`, null);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const workspaceActorRefs = actorRefsByWorkspace.get(workspaceId) ?? new Set();
|
|
133
|
+
workspaceActorRefs.add(actorRef);
|
|
134
|
+
actorRefsByWorkspace.set(workspaceId, workspaceActorRefs);
|
|
135
|
+
}
|
|
136
|
+
for (const [workspaceId, actorRefs] of actorRefsByWorkspace) {
|
|
137
|
+
const resolvedWorkspaceActors = deps.resolveWorkspaceActors(workspaceId, [...actorRefs]);
|
|
138
|
+
for (const actorRef of actorRefs) {
|
|
139
|
+
actorProfiles.set(`${workspaceId}\u0000${actorRef}`, resolvedWorkspaceActors.get(actorRef) ?? null);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const cachedDeps = {
|
|
143
|
+
...deps,
|
|
144
|
+
resolveWorkspaceActor: (workspaceId, actorRef) => {
|
|
145
|
+
const cacheKey = `${workspaceId}\u0000${String(actorRef || '').trim()}`;
|
|
146
|
+
if (actorProfiles.has(cacheKey))
|
|
147
|
+
return actorProfiles.get(cacheKey) ?? null;
|
|
148
|
+
const actorProfile = deps.resolveWorkspaceActor(workspaceId, actorRef);
|
|
149
|
+
actorProfiles.set(cacheKey, actorProfile);
|
|
150
|
+
return actorProfile;
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
return rows
|
|
154
|
+
.map((row) => mapDeletedTaskRowService(cachedDeps, row))
|
|
155
|
+
.filter((row) => Boolean(row));
|
|
156
|
+
}
|
|
122
157
|
function deletedTaskListSnapshotSelect() {
|
|
123
158
|
const snapshotPairs = DELETED_TASK_LIST_SNAPSHOT_FIELDS
|
|
124
159
|
.map((field) => `'${field}', snapshot -> '${field}'`)
|
|
@@ -220,9 +255,7 @@ export function listDeletedTasksService(deps, workspaceId) {
|
|
|
220
255
|
`;
|
|
221
256
|
const rows = deps.db.prepare(listSql).all(deps.tenantId, normalizedWorkspaceId);
|
|
222
257
|
return {
|
|
223
|
-
deleted: rows
|
|
224
|
-
.map((row) => mapDeletedTaskRowService(deps, row))
|
|
225
|
-
.filter((row) => Boolean(row))
|
|
258
|
+
deleted: mapDeletedTaskRowsService(deps, rows)
|
|
226
259
|
};
|
|
227
260
|
}
|
|
228
261
|
export function listDeletedTasksReadOnlyService(deps, workspaceId) {
|
|
@@ -240,9 +273,7 @@ export function listDeletedTasksReadOnlyService(deps, workspaceId) {
|
|
|
240
273
|
`;
|
|
241
274
|
const rows = deps.db.prepare(listSql).all(deps.tenantId, normalizedWorkspaceId);
|
|
242
275
|
return {
|
|
243
|
-
deleted: rows
|
|
244
|
-
.map((row) => mapDeletedTaskRowService(deps, row))
|
|
245
|
-
.filter((row) => Boolean(row))
|
|
276
|
+
deleted: mapDeletedTaskRowsService(deps, rows)
|
|
246
277
|
.filter((row) => row.deletedAt >= cutoff || durableDeleteOwnedTaskIds.has(row.taskId))
|
|
247
278
|
};
|
|
248
279
|
}
|