@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.
Files changed (485) hide show
  1. package/dist/Taskforce.module.css +523 -79
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AiProfilesModule.js +3 -5
  8. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  9. package/dist/components/features/TaskSettings.d.ts +12 -1
  10. package/dist/components/features/TaskSettings.js +217 -54
  11. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  12. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  13. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  14. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  15. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  16. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  17. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  18. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  19. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  20. package/dist/components/features/planning/PlanningModule.js +2 -5
  21. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  22. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  23. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  24. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  25. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  26. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  27. package/dist/components/features/taskforceAgentEditorModel.js +5 -1
  28. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  29. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +65 -10
  32. package/dist/components/task/TaskImageReviews.js +14 -5
  33. package/dist/components/task/TaskKanban.d.ts +6 -1
  34. package/dist/components/task/TaskKanban.js +152 -6
  35. package/dist/components/task/TaskList.d.ts +5 -0
  36. package/dist/components/task/TaskList.js +3 -3
  37. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  38. package/dist/components/ui/PasswordInput.d.ts +6 -0
  39. package/dist/components/ui/PasswordInput.js +11 -0
  40. package/dist/components/ui/TopNoticeLayer.js +1 -1
  41. package/dist/components/views/AppShellHeader.js +32 -11
  42. package/dist/components/views/PlanComparisonPage.js +12 -0
  43. package/dist/components/views/StandaloneLayout.js +32 -55
  44. package/dist/components/views/WidgetView.js +3 -3
  45. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  46. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  47. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  48. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  49. package/dist/config/envSchema.js +60 -1
  50. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  51. package/dist/config/localServiceRuntimeContract.js +135 -0
  52. package/dist/core/AiProfileService.js +46 -8
  53. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  54. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  55. package/dist/core/McpTokenService.d.ts +23 -1
  56. package/dist/core/McpTokenService.js +93 -10
  57. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  58. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  59. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  60. package/dist/core/TaskChecklistCommandService.js +83 -5
  61. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  62. package/dist/core/TaskLifecycleCommandService.js +6 -2
  63. package/dist/core/Taskforce.d.ts +94 -2
  64. package/dist/core/Taskforce.js +760 -36
  65. package/dist/core/types.d.ts +14 -0
  66. package/dist/documentReviews/commandService.d.ts +2 -1
  67. package/dist/documentReviews/commandService.js +6 -3
  68. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  69. package/dist/hooks/sync/orchestratorShared.js +2 -0
  70. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  71. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  72. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  73. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  74. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  75. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  76. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  77. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  78. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  79. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  80. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  81. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  82. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  83. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  84. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  85. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  86. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  87. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  88. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  89. package/dist/hooks/ui/useSettingsModel.js +13 -2
  90. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  91. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  92. package/dist/hooks/useFilterSort.d.ts +7 -3
  93. package/dist/hooks/useFilterSort.js +15 -5
  94. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  95. package/dist/hooks/useSyncOrchestrator.js +111 -2
  96. package/dist/hooks/useTaskData.d.ts +40 -1
  97. package/dist/hooks/useTaskData.js +240 -9
  98. package/dist/hooks/useTaskMutations.d.ts +12 -2
  99. package/dist/hooks/useTaskMutations.js +266 -52
  100. package/dist/hooks/useTaskforce.d.ts +39 -9
  101. package/dist/hooks/useTaskforce.js +359 -40
  102. package/dist/hooks/useUiNotice.d.ts +4 -0
  103. package/dist/hooks/useUiNotice.js +4 -0
  104. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  105. package/dist/mcp/clientRegistry.d.ts +2 -2
  106. package/dist/mcp/clientRegistry.js +1 -1
  107. package/dist/mcp/documentAssetRegistrar.js +53 -41
  108. package/dist/mcp/documentHelpers.d.ts +1 -0
  109. package/dist/mcp/documentHelpers.js +7 -3
  110. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  111. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  112. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  113. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  114. package/dist/mcp/httpProtocolRouting.js +19 -0
  115. package/dist/mcp/localCliHealth.d.ts +2 -2
  116. package/dist/mcp/localCliHealth.js +2 -2
  117. package/dist/mcp/localServiceProxy.d.ts +1 -0
  118. package/dist/mcp/localServiceProxy.js +530 -68
  119. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  120. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  121. package/dist/mcp/runtime.d.ts +54 -79
  122. package/dist/mcp/runtime.js +556 -139
  123. package/dist/mcp/taskPlanningRegistrar.js +64 -42
  124. package/dist/mcp/toolCallCompatibility.js +38 -1
  125. package/dist/mcp/toolCatalog.d.ts +1 -0
  126. package/dist/mcp/toolProfiles.d.ts +2 -0
  127. package/dist/mcp/toolProfiles.js +10 -0
  128. package/dist/mcp/toolRegistry.d.ts +1 -0
  129. package/dist/mcp/toolRegistry.js +1 -0
  130. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  131. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  132. package/dist/migrations/taskSchemaMigrations.js +427 -0
  133. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  134. package/dist/runtime/appGateDefinitions.js +6 -6
  135. package/dist/runtime/appGates.d.ts +13 -13
  136. package/dist/runtime/appGates.js +36 -13
  137. package/dist/runtime/nodeAppGates.d.ts +8 -0
  138. package/dist/runtime/nodeAppGates.js +27 -0
  139. package/dist/server/cloudCollectionRead.d.ts +1 -1
  140. package/dist/server/cloudCollectionRead.js +2 -2
  141. package/dist/server/index.d.ts +6 -0
  142. package/dist/server/index.js +123 -14
  143. package/dist/server/localDatabaseIdentity.js +4 -1
  144. package/dist/server/localServiceLease.d.ts +3 -0
  145. package/dist/server/localServiceLease.js +11 -2
  146. package/dist/server/localServiceSessions.d.ts +14 -17
  147. package/dist/server/localServiceSessions.js +308 -94
  148. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
  149. package/dist/server/rateLimit.d.ts +1 -0
  150. package/dist/server/rateLimit.js +4 -0
  151. package/dist/server/realtimeSyncWs.js +36 -12
  152. package/dist/server/routes/admin.d.ts +4 -0
  153. package/dist/server/routes/admin.js +113 -3
  154. package/dist/server/routes/agentRoles.js +3 -2
  155. package/dist/server/routes/agentSkills.js +3 -2
  156. package/dist/server/routes/agents.d.ts +7 -0
  157. package/dist/server/routes/agents.js +394 -39
  158. package/dist/server/routes/annotatedAttachments.js +3 -2
  159. package/dist/server/routes/auth.js +3 -1
  160. package/dist/server/routes/billing.js +5 -1
  161. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  162. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  163. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  164. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  165. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  166. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  167. package/dist/server/routes/githubReviewEvidence.js +116 -0
  168. package/dist/server/routes/localService.d.ts +15 -4
  169. package/dist/server/routes/localService.js +138 -40
  170. package/dist/server/routes/modelConnections.d.ts +24 -0
  171. package/dist/server/routes/modelConnections.js +205 -0
  172. package/dist/server/routes/primitives.d.ts +2 -0
  173. package/dist/server/routes/shared.d.ts +19 -0
  174. package/dist/server/routes/shared.js +95 -19
  175. package/dist/server/routes/sync.js +1 -0
  176. package/dist/server/routes/syncAuxRoutes.js +9 -2
  177. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  178. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  179. package/dist/server/routes/syncPushRoutes.js +1 -0
  180. package/dist/server/routes/syncV3FeedRoutes.js +27 -16
  181. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  182. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  183. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  184. package/dist/server/routes/syncV3OperationRoutes.js +45 -9
  185. package/dist/server/routes/tasks.js +124 -13
  186. package/dist/server/routes/workflows.js +9 -1
  187. package/dist/server/routes/workspaces.js +43 -1
  188. package/dist/server/routes.js +59 -0
  189. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  190. package/dist/server/workspaceDeletionAdmission.js +50 -0
  191. package/dist/service/localServiceCli.js +16 -0
  192. package/dist/service/localServiceClientLifecycle.js +36 -10
  193. package/dist/services/codexAppServerModelGateway.d.ts +161 -0
  194. package/dist/services/codexAppServerModelGateway.js +663 -0
  195. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  196. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  197. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  198. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  199. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  200. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  201. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  202. package/dist/services/executorPhaseAApprovalService.js +609 -0
  203. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  204. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  205. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  206. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  207. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  208. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  209. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  210. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  211. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  212. package/dist/services/githubReviewEvidenceService.js +336 -0
  213. package/dist/services/modelGateway.d.ts +7 -0
  214. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  215. package/dist/services/modelProviderConnectionService.js +279 -0
  216. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  217. package/dist/services/modelProviderCredentialHome.js +271 -0
  218. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  219. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  220. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  221. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  222. package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
  223. package/dist/services/taskforceAgentMcpBridge.js +30 -27
  224. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  225. package/dist/shared/adminEdgeProxy.js +94 -0
  226. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  227. package/dist/shared/adminProxySessionCookies.js +86 -0
  228. package/dist/shared/aiProfileColors.d.ts +31 -1
  229. package/dist/shared/aiProfileColors.js +14 -6
  230. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  231. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  232. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  233. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  234. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  235. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  236. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  237. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  238. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  239. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  240. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  241. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  242. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  243. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  244. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  245. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  246. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  247. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  248. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  249. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  250. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  251. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  252. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  253. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  254. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  255. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  256. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  257. package/dist/shared/executorPhaseATiming.js +1 -0
  258. package/dist/shared/planningIdentity.js +1 -1
  259. package/dist/shared/productLogoKeys.d.ts +2 -0
  260. package/dist/shared/productLogoKeys.js +18 -0
  261. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  262. package/dist/shared/taskforceAgentDefinition.js +6 -3
  263. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  264. package/dist/shared/taskforceAgentModels.js +36 -3
  265. package/dist/shared/userFeatureGrants.d.ts +4 -0
  266. package/dist/shared/userFeatureGrants.js +7 -0
  267. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  268. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  269. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  270. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  271. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  272. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  273. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  274. package/dist/storage/modelProviderConnectionStore.js +446 -0
  275. package/dist/storage/postgresAdapter.d.ts +24 -3
  276. package/dist/storage/postgresAdapter.js +117 -14
  277. package/dist/storage/postgresWorker.js +22 -5
  278. package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
  279. package/dist/storage/postgresWorkerProtocol.js +30 -0
  280. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  281. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  282. package/dist/sync/cloudSyncApi.d.ts +4 -1
  283. package/dist/sync/cloudSyncApi.js +7 -2
  284. package/dist/sync/contentSyncState.d.ts +1 -1
  285. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  286. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
  287. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  288. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  289. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  290. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  291. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  292. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  293. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  294. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  295. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  296. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  297. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  298. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  299. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  300. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  301. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  302. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  303. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  304. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  305. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  306. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  307. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  308. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  309. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  310. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
  311. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  312. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  313. package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
  314. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  315. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  316. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  317. package/dist/sync/syncApplyHandlers.js +10 -1
  318. package/dist/sync/syncService.d.ts +17 -0
  319. package/dist/sync/syncService.js +87 -19
  320. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  321. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  322. package/dist/sync/v3/combinedFeedCapability.js +8 -0
  323. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  324. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  325. package/dist/sync/v3/durableOperationReplay.js +18 -0
  326. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  327. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
  328. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
  329. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
  330. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  331. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  332. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  333. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  334. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
  335. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  336. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  337. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  338. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  339. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  340. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  341. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  342. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  343. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  344. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  345. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  346. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  347. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  348. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  349. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  350. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  351. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  352. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  353. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  354. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  355. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
  356. package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
  357. package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
  358. package/dist/sync/v3/syncDurabilityStore.js +199 -13
  359. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  360. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  361. package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
  362. package/dist/sync/v3/taskChecklistMutationService.js +48 -1
  363. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  364. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  365. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  366. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  367. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  368. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  369. package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
  370. package/dist/sync/v3/taskStatusMutationService.js +123 -3
  371. package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
  372. package/dist/sync/v3/workflowAssignmentSync.js +30 -0
  373. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  374. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  375. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  376. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  377. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  378. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  379. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  380. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  381. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  382. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  383. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
  384. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  385. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  386. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
  387. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
  388. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
  389. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
  390. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
  391. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
  392. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
  393. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
  394. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
  395. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  396. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  397. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  398. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  399. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  400. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  401. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  402. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  403. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  404. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  405. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  406. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
  407. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
  408. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
  409. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  410. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  411. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  412. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  413. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  414. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  415. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  416. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  417. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  418. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  419. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  420. package/dist/sync/workspacePullFeed.js +2 -1
  421. package/dist/sync/workspaceRepair.d.ts +8 -2
  422. package/dist/sync/workspaceRepair.js +222 -6
  423. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  424. package/dist/sync/workspaceSyncModel.js +35 -7
  425. package/dist/sync/workspaceSyncState.d.ts +1 -0
  426. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  427. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  428. package/dist/types.d.ts +47 -1
  429. package/dist/types.js +6 -0
  430. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  431. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  432. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
  433. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  434. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  435. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
  436. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  437. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  438. package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
  439. package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
  440. package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
  441. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  442. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  443. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  444. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  445. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  446. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  447. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
  448. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  449. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  450. package/dist/ui/branding/logos/signature_dark.png +0 -0
  451. package/dist/ui/branding/logos/signature_light.png +0 -0
  452. package/dist/ui/index.html +3 -3
  453. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  454. package/dist/utils/httpSetCookie.d.ts +1 -0
  455. package/dist/utils/httpSetCookie.js +4 -1
  456. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  457. package/dist/utils/localRuntimeUrl.js +14 -0
  458. package/dist/utils/productLogoRegistry.d.ts +2 -0
  459. package/dist/utils/productLogoRegistry.js +36 -0
  460. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  461. package/dist/utils/syncStatusPresentation.js +17 -0
  462. package/dist/utils/taskActivity.d.ts +3 -2
  463. package/dist/utils/taskActivity.js +19 -2
  464. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  465. package/dist/utils/taskEditorReconciliation.js +217 -0
  466. package/dist/utils/taskEvents.d.ts +2 -0
  467. package/dist/utils/taskNormalization.d.ts +1 -0
  468. package/dist/utils/taskNormalization.js +39 -0
  469. package/dist/utils/taskSearch.js +2 -2
  470. package/dist/utils/uiNotice.d.ts +4 -0
  471. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  472. package/dist/utils/workspaceSyncPresentation.js +23 -17
  473. package/package.json +36 -6
  474. package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
  475. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  476. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  477. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  478. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  479. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  480. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  481. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  482. package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
  483. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  484. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  485. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -27,11 +27,11 @@ import { parseWorkspaceSyncV3OriginActor, } from '../../sync/v3/workspaceSyncV3O
27
27
  import { validateWorkspaceSyncV3TaskCommentReconcileProvenance, verifyWorkspaceSyncV3TaskCommentReconcileProvenance, } from '../../sync/v3/taskCommentReconcileProvenance.js';
28
28
  import { isStrongWorkspaceSyncV3OriginAssertionProfileToken, verifyWorkspaceSyncV3OriginAssertion, WORKSPACE_SYNC_V3_ORIGIN_ASSERTION_HEADER, workspaceSyncV3OriginAssertionBinding, } from '../../sync/v3/workspaceSyncV3OriginAssertion.js';
29
29
  import { validateWorkflowRuntimeMutationCommand } from '../../sync/v3/workflowRuntimeSync.js';
30
- import { resolveWorkflowRuntimeMutationCapability } from '../../sync/v3/durableWorkflowRuntimeMutationRouter.js';
31
- import { normalizeWorkflowAssignmentSyncRecord, WorkflowAssignmentSyncError, } from '../../sync/v3/workflowAssignmentSync.js';
30
+ import { resolveWorkflowRuntimeDurableTransportCapability } from '../../sync/v3/durableWorkflowRuntimeMutationRouter.js';
31
+ import { normalizeTaskStatusOperationWithWorkflowAssignment, WorkflowAssignmentSyncError, } from '../../sync/v3/workflowAssignmentSync.js';
32
32
  import { WorkflowAssignmentSyncConflictError } from '../../storage/workflowStore.js';
33
33
  import { DurableTaskCommentMutationError } from '../../sync/v3/taskCommentMutationService.js';
34
- import { DurableTaskChecklistMutationError } from '../../sync/v3/taskChecklistMutationService.js';
34
+ import { DurableTaskChecklistMutationError, validateTaskChecklistItemUpdateIntent, } from '../../sync/v3/taskChecklistMutationService.js';
35
35
  import { DurableTaskAttachmentLinksMutationError } from '../../sync/v3/taskAttachmentLinksMutationService.js';
36
36
  import { validateWorkspaceSyncV3TaskAttachmentLinksPayload, validateWorkspaceSyncV3TaskChecklistPayload, validateWorkspaceSyncV3TaskCommentsPayload, } from '../../sync/v3/workspaceSyncV3NestedTaskCodecs.js';
37
37
  import { parseJsonBody } from './primitives.js';
@@ -157,9 +157,13 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
157
157
  const payload = requireObject(operation.payload, 'operation.payload');
158
158
  if (operation.domain === 'task' && operation.mutationKind === 'metadata-update') {
159
159
  const saveSource = payload.saveSource;
160
+ const expectedDetailRevision = payload.expectedDetailRevision === undefined
161
+ ? undefined
162
+ : requireId(payload.expectedDetailRevision, 'operation.payload.expectedDetailRevision');
160
163
  assertExactKeys(payload, [
161
164
  'patch',
162
165
  ...(saveSource === undefined ? [] : ['saveSource']),
166
+ ...(expectedDetailRevision === undefined ? [] : ['expectedDetailRevision']),
163
167
  ...(payload.originActor === undefined ? [] : ['originActor']),
164
168
  ], 'operation.payload');
165
169
  if (saveSource !== undefined && saveSource !== 'manual' && saveSource !== 'autosave') {
@@ -173,6 +177,7 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
173
177
  payload: {
174
178
  patch: requireObject(payload.patch, 'operation.payload.patch'),
175
179
  ...(saveSource ? { saveSource } : {}),
180
+ ...(expectedDetailRevision ? { expectedDetailRevision } : {}),
176
181
  ...(originActor ? { originActor } : {}),
177
182
  },
178
183
  } };
@@ -363,7 +368,9 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
363
368
  assertExactKeys(payload, [
364
369
  ...baseKeys,
365
370
  ...(payload.workflowAssignment === undefined ? [] : ['workflowAssignment']),
371
+ ...(payload.reviewHandoff === undefined ? [] : ['reviewHandoff']),
366
372
  ...(payload.originActor === undefined ? [] : ['originActor']),
373
+ ...(payload.expectedDetailRevision === undefined ? [] : ['expectedDetailRevision']),
367
374
  ], 'operation.payload');
368
375
  const normalizedPayload = validateDurableTaskStatusMutationPayload({
369
376
  status: payload.status,
@@ -371,9 +378,8 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
371
378
  canceledReason: payload.canceledReason,
372
379
  metadataPatch: payload.metadataPatch,
373
380
  });
374
- const workflowAssignment = payload.workflowAssignment === undefined
375
- ? undefined
376
- : normalizeWorkflowAssignmentSyncRecord(payload.workflowAssignment);
381
+ const normalizedOperationPayload = normalizeTaskStatusOperationWithWorkflowAssignment(payload);
382
+ const workflowAssignment = normalizedOperationPayload.workflowAssignment;
377
383
  if (workflowAssignment
378
384
  && (normalizedPayload.status !== 'in-progress'
379
385
  || workflowAssignment.execution.taskId !== entityId)) {
@@ -382,12 +388,19 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
382
388
  const originActor = payload.originActor === undefined
383
389
  ? undefined
384
390
  : requireOriginActor(payload.originActor);
391
+ const expectedDetailRevision = payload.expectedDetailRevision === undefined
392
+ ? undefined
393
+ : requireId(payload.expectedDetailRevision, 'operation.payload.expectedDetailRevision');
385
394
  return { ...common, operation: {
386
395
  domain: 'task', entityId, mutationKind: 'set-status', baseEntityRevision, baseLifecycleRevision,
387
396
  payload: {
388
397
  ...normalizedPayload,
389
398
  ...(workflowAssignment ? { workflowAssignment } : {}),
399
+ ...(normalizedOperationPayload.reviewHandoff
400
+ ? { reviewHandoff: normalizedOperationPayload.reviewHandoff }
401
+ : {}),
390
402
  ...(originActor ? { originActor } : {}),
403
+ ...(expectedDetailRevision ? { expectedDetailRevision } : {}),
391
404
  },
392
405
  } };
393
406
  }
@@ -450,7 +463,24 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
450
463
  if (baseLifecycleRevision !== '0') {
451
464
  throw new SyncV3RequestError('Task checklist lifecycle revision must be 0.');
452
465
  }
453
- assertExactKeys(payload, payload.originActor === undefined ? ['items'] : ['items', 'originActor'], 'operation.payload');
466
+ const expectedDetailRevision = payload.expectedDetailRevision === undefined
467
+ ? undefined
468
+ : requireId(payload.expectedDetailRevision, 'operation.payload.expectedDetailRevision');
469
+ let itemUpdateIntent;
470
+ try {
471
+ itemUpdateIntent = payload.itemUpdateIntent === undefined
472
+ ? undefined
473
+ : validateTaskChecklistItemUpdateIntent(payload.itemUpdateIntent);
474
+ }
475
+ catch (error) {
476
+ throw new SyncV3RequestError(error instanceof Error ? error.message : 'operation.payload.itemUpdateIntent is invalid.');
477
+ }
478
+ assertExactKeys(payload, [
479
+ 'items',
480
+ ...(expectedDetailRevision === undefined ? [] : ['expectedDetailRevision']),
481
+ ...(itemUpdateIntent === undefined ? [] : ['itemUpdateIntent']),
482
+ ...(payload.originActor === undefined ? [] : ['originActor']),
483
+ ], 'operation.payload');
454
484
  let items;
455
485
  try {
456
486
  items = validateWorkspaceSyncV3TaskChecklistPayload({ taskId: entityId, items: payload.items }).items;
@@ -464,7 +494,12 @@ export function parseWorkspaceSyncV3OperationEnvelope(body) {
464
494
  return { ...common, operation: {
465
495
  domain: 'task-checklist', entityId, mutationKind: 'replace', baseEntityRevision,
466
496
  baseLifecycleRevision: '0',
467
- payload: { items, ...(originActor ? { originActor } : {}) },
497
+ payload: {
498
+ items,
499
+ ...(expectedDetailRevision ? { expectedDetailRevision } : {}),
500
+ ...(itemUpdateIntent ? { itemUpdateIntent } : {}),
501
+ ...(originActor ? { originActor } : {}),
502
+ },
468
503
  } };
469
504
  }
470
505
  if (operation.domain === 'task-attachment-links' && operation.mutationKind === 'replace') {
@@ -720,7 +755,7 @@ export function registerWorkspaceSyncV3OperationRoutes(input) {
720
755
  const taxonomyEnabled = input.taxonomyEnabled ?? isWorkspaceSyncV3TaxonomyEnabled();
721
756
  const initiativeEnabled = input.initiativeEnabled ?? isWorkspaceSyncV3InitiativesEnabled();
722
757
  const workstreamEnabled = input.workstreamEnabled ?? isWorkspaceSyncV3WorkstreamsEnabled();
723
- const workflowRuntimeEnabled = input.workflowRuntimeEnabled ?? resolveWorkflowRuntimeMutationCapability({
758
+ const workflowRuntimeEnabled = input.workflowRuntimeEnabled ?? resolveWorkflowRuntimeDurableTransportCapability({
724
759
  runtimeMode: 'cloud',
725
760
  surface: 'http',
726
761
  env: input.env,
@@ -1016,6 +1051,7 @@ export function registerWorkspaceSyncV3OperationRoutes(input) {
1016
1051
  operationId: envelope.operationId,
1017
1052
  errorCode: String(error?.code || 'POST_COMMIT_EFFECT_FAILED').slice(0, 100),
1018
1053
  }),
1054
+ includeWorkflowRuntimeJournal: workflowRuntimeEnabled,
1019
1055
  };
1020
1056
  const operationWasCommitted = Boolean(store.readCommittedOperationResponse({
1021
1057
  tenantId: input.core.getTenantId(),
@@ -69,6 +69,7 @@ import { createDurableWorkstreamMutationRouter } from '../../sync/v3/durableWork
69
69
  import { createDurableWorkstreamTaskOrderMutationRouter } from '../../sync/v3/durableWorkstreamTaskOrderMutationRouter.js';
70
70
  import { serializeCanonicalPlanningAttachmentLinks } from '../../sync/planningCanonicalFields.js';
71
71
  import { createTaskHttpDurableRouters } from './durableTaskHttpRouters.js';
72
+ import { WorkspaceSyncDurabilityStore } from '../../sync/v3/syncDurabilityStore.js';
72
73
  // === SECTION: Module dependency interface ===
73
74
  const UI_STATE_MAX_JSON_BODY_BYTES = 50 * 1024 * 1024;
74
75
  function normalizeDurableChecklistItems(input) {
@@ -470,15 +471,89 @@ export function registerTaskRoutes(deps) {
470
471
  res,
471
472
  route: '/api/taskforce/tasks',
472
473
  workspaceId,
473
- load: () => core.listTasks(workspaceId),
474
+ // Local V2 sync still builds an outbound snapshot from these collections.
475
+ // Keep its full graph until that writer is retired; cloud is read-authoritative.
476
+ load: () => (context.authConfig?.runtimeMode === 'cloud' ? 'cloud' : requestRuntimeMode(req)) === 'cloud'
477
+ ? core.listActiveTaskSummaries(workspaceId)
478
+ : core.listTasks(workspaceId),
474
479
  });
475
480
  });
481
+ // GET /api/taskforce/tasks/search - Search lightweight task summaries across lifecycles
482
+ addRoute('GET', '/api/taskforce/tasks/search', async (req, res) => {
483
+ if (!ensureAppAccess(req, res))
484
+ return;
485
+ try {
486
+ const requestUrl = new URL(req.url || '', 'http://localhost');
487
+ const query = String(requestUrl.searchParams.get('query') || '').trim();
488
+ if (!query) {
489
+ throw new TaskforceRuleError('query is required.', 400, 'TASK_SEARCH_QUERY_REQUIRED');
490
+ }
491
+ if (query.length > 200) {
492
+ throw new TaskforceRuleError('query must be 200 characters or fewer.', 400, 'TASK_SEARCH_QUERY_TOO_LONG');
493
+ }
494
+ const scopeInput = String(requestUrl.searchParams.get('scope') || 'all').trim();
495
+ if (!['all', 'active', 'archive'].includes(scopeInput)) {
496
+ throw new TaskforceRuleError('scope must be all, active, or archive.', 400, 'TASK_SEARCH_SCOPE_INVALID');
497
+ }
498
+ const parseBoundedInteger = (name, fallback, max) => {
499
+ const raw = requestUrl.searchParams.get(name);
500
+ if (raw === null || raw === '')
501
+ return fallback;
502
+ const parsed = Number(raw);
503
+ if (!Number.isInteger(parsed) || parsed < (name === 'limit' ? 1 : 0) || parsed > max) {
504
+ throw new TaskforceRuleError(`${name} must be an integer between ${name === 'limit' ? 1 : 0} and ${max}.`, 400, `TASK_SEARCH_${name.toUpperCase()}_INVALID`);
505
+ }
506
+ return parsed;
507
+ };
508
+ const limit = parseBoundedInteger('limit', 50, 50);
509
+ const offset = parseBoundedInteger('offset', 0, 10_000);
510
+ const workspaceId = requestWorkspaceId(req);
511
+ const rows = core.searchTaskSummaries(query, scopeInput, workspaceId, { limit: limit + 1, offset });
512
+ const hasMore = rows.length > limit;
513
+ const matches = rows.slice(0, limit);
514
+ res.writeHead(200, { 'Content-Type': 'application/json' });
515
+ res.end(JSON.stringify({
516
+ matches,
517
+ pagination: {
518
+ limit,
519
+ offset,
520
+ returned: matches.length,
521
+ hasMore,
522
+ nextOffset: hasMore ? offset + matches.length : null,
523
+ },
524
+ }));
525
+ }
526
+ catch (error) {
527
+ const statusCode = resolveErrorStatusCode(error, 400);
528
+ const message = error instanceof Error ? error.message : 'Failed to search tasks.';
529
+ const code = error instanceof TaskforceRuleError ? error.code : error?.code;
530
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
531
+ res.end(JSON.stringify({ error: message, code }));
532
+ }
533
+ });
476
534
  addRoute('GET', '/api/taskforce/task-relationships', async (req, res) => {
477
535
  if (!ensureAppAccess(req, res))
478
536
  return;
479
537
  const workspaceId = requestWorkspaceId(req);
538
+ const relationships = core.listTaskRelationshipsForSync(workspaceId);
539
+ const requestUrl = new URL(req.url || '', 'http://localhost');
540
+ const includeSyncCoordinates = requestUrl.searchParams.get('includeSyncCoordinates') === 'true';
541
+ const durabilityStore = includeSyncCoordinates
542
+ ? new WorkspaceSyncDurabilityStore(core.getDatabaseAdapter())
543
+ : null;
544
+ const syncCoordinates = durabilityStore
545
+ ? Object.fromEntries(relationships.map((relationship) => [
546
+ relationship.id,
547
+ durabilityStore.readEntityRevisionCoordinates({
548
+ tenantId: core.getTenantId(),
549
+ workspaceId,
550
+ domain: 'task-relationship',
551
+ entityId: relationship.id,
552
+ }),
553
+ ]))
554
+ : undefined;
480
555
  res.writeHead(200, { 'Content-Type': 'application/json' });
481
- res.end(JSON.stringify({ relationships: core.listTaskRelationshipsForSync(workspaceId) }));
556
+ res.end(JSON.stringify({ relationships, ...(syncCoordinates ? { syncCoordinates } : {}) }));
482
557
  });
483
558
  const handleListDeletedTasks = async (req, res) => {
484
559
  if (!ensureAppAccess(req, res))
@@ -544,7 +619,8 @@ export function registerTaskRoutes(deps) {
544
619
  res.writeHead(200, { 'Content-Type': 'application/json' });
545
620
  res.end(JSON.stringify({ dataVersion }));
546
621
  });
547
- // GET /api/taskforce/health - Lightweight readiness signal for API + DB
622
+ // GET /api/taskforce/health - Bounded, non-mutating readiness signal for API + DB.
623
+ // `/api/taskforce/version` remains the dependency-free process/build liveness signal.
548
624
  addRoute('GET', '/api/taskforce/health', async (req, res) => {
549
625
  const healthy = core.isDatabaseHealthy();
550
626
  const payload = {
@@ -617,6 +693,20 @@ export function registerTaskRoutes(deps) {
617
693
  }));
618
694
  }
619
695
  });
696
+ // GET /api/taskforce/task/:id - Read complete active or archived task detail
697
+ addRoute('GET', '/api/taskforce/task/:id', async (req, res, params) => {
698
+ if (!ensureAppAccess(req, res))
699
+ return;
700
+ const workspaceId = requestWorkspaceId(req);
701
+ const task = core.getTaskDetailSnapshot(params.id, workspaceId);
702
+ if (!task) {
703
+ res.writeHead(404, { 'Content-Type': 'application/json' });
704
+ res.end(JSON.stringify({ error: 'Task not found' }));
705
+ return;
706
+ }
707
+ res.writeHead(200, { 'Content-Type': 'application/json' });
708
+ res.end(JSON.stringify(task));
709
+ });
620
710
  // PATCH /api/taskforce/task/:id - Update a task
621
711
  addRoute('PATCH', '/api/taskforce/task/:id', async (req, res, params) => {
622
712
  if (!ensureAppAccess(req, res))
@@ -625,8 +715,15 @@ export function registerTaskRoutes(deps) {
625
715
  try {
626
716
  const workspaceId = requestWorkspaceId(req);
627
717
  const saveSource = body?.saveSource === 'autosave' ? 'autosave' : 'manual';
718
+ const expectedDetailRevision = typeof body?.expectedDetailRevision === 'string'
719
+ ? body.expectedDetailRevision.trim()
720
+ : null;
721
+ if (body && Object.prototype.hasOwnProperty.call(body, 'expectedDetailRevision')
722
+ && !expectedDetailRevision) {
723
+ throw new TaskforceRuleError('expectedDetailRevision must be a non-empty string.', 400, 'TASK_DETAIL_REVISION_INVALID');
724
+ }
628
725
  const updates = body && typeof body === 'object'
629
- ? Object.fromEntries(Object.entries(body).filter(([key]) => key !== 'saveSource'))
726
+ ? Object.fromEntries(Object.entries(body).filter(([key]) => (key !== 'saveSource' && key !== 'expectedDetailRevision')))
630
727
  : body;
631
728
  const durableRouters = createTaskHttpDurableRouters({ core, context, req, workspaceId });
632
729
  const durableRouter = durableRouters.root;
@@ -658,10 +755,14 @@ export function registerTaskRoutes(deps) {
658
755
  const durableTargetCount = Number(checklistDurable)
659
756
  + Number(attachmentLinksDurable)
660
757
  + Number(Object.keys(remainingUpdates).length > 0);
661
- if (durableTargetCount > 1) {
758
+ if (durableTargetCount > 1 || Boolean(expectedDetailRevision && (checklistDurable || attachmentLinksDurable))) {
662
759
  const aggregate = durableRouters.bulk.updateFields([
663
760
  { id: params.id, ...updates },
664
- ], { saveSource, atomicItemFailures: true });
761
+ ], {
762
+ saveSource,
763
+ atomicItemFailures: true,
764
+ ...(expectedDetailRevision ? { expectedDetailRevision } : {}),
765
+ });
665
766
  const failure = aggregate.errors[0];
666
767
  if (failure) {
667
768
  throw new TaskforceRuleError(failure.message, failure.statusCode, failure.code || 'TASK_UPDATE_FAILED', failure.details);
@@ -671,11 +772,13 @@ export function registerTaskRoutes(deps) {
671
772
  else {
672
773
  updated = Object.keys(remainingUpdates || {}).length > 0
673
774
  ? (durableRouter.enabled
674
- ? durableRouter.update(params.id, remainingUpdates, saveSource)
675
- : core.updateTask(params.id, remainingUpdates, workspaceId, {
676
- actorRef: requestHumanActorRef(req),
677
- saveSource,
678
- }))
775
+ ? durableRouter.update(params.id, remainingUpdates, saveSource, undefined, expectedDetailRevision || undefined)
776
+ : expectedDetailRevision !== null
777
+ ? core.updateTaskIfDetailRevisionMatches(params.id, expectedDetailRevision, remainingUpdates, workspaceId, { actorRef: requestHumanActorRef(req), saveSource })
778
+ : core.updateTask(params.id, remainingUpdates, workspaceId, {
779
+ actorRef: requestHumanActorRef(req),
780
+ saveSource,
781
+ }))
679
782
  : core.getTask(params.id, workspaceId);
680
783
  if (updated && checklistDurable) {
681
784
  const checklistRouter = durableRouters.createChecklistRouter(durableRouters.deriveChildOperationId('task-patch-checklist', 0, params.id));
@@ -711,8 +814,14 @@ export function registerTaskRoutes(deps) {
711
814
  res.end(JSON.stringify({ error: 'Task not found' }));
712
815
  return;
713
816
  }
817
+ const authoritative = core.getTaskDetailSnapshot(params.id, workspaceId);
818
+ if (!authoritative) {
819
+ res.writeHead(404, { 'Content-Type': 'application/json' });
820
+ res.end(JSON.stringify({ error: 'Task not found' }));
821
+ return;
822
+ }
714
823
  res.writeHead(200, { 'Content-Type': 'application/json' });
715
- res.end(JSON.stringify(updated));
824
+ res.end(JSON.stringify(authoritative));
716
825
  }
717
826
  catch (error) {
718
827
  const statusCode = resolveErrorStatusCode(error, 400);
@@ -1291,7 +1400,9 @@ export function registerTaskRoutes(deps) {
1291
1400
  res,
1292
1401
  route: '/api/taskforce/archive',
1293
1402
  workspaceId,
1294
- load: () => core.listArchive(workspaceId),
1403
+ load: () => (context.authConfig?.runtimeMode === 'cloud' ? 'cloud' : requestRuntimeMode(req)) === 'cloud'
1404
+ ? core.listArchiveSummaries(workspaceId)
1405
+ : core.listArchive(workspaceId),
1295
1406
  });
1296
1407
  });
1297
1408
  // POST /api/taskforce/task/:id/complete - Archive as complete
@@ -8,7 +8,7 @@ import { WorkflowStore } from '../../storage/workflowStore.js';
8
8
  import { createDurableTaskHttpRootMutationRouter } from '../../sync/v3/durableTaskHttpRootMutationRouter.js';
9
9
  import { fingerprintWorkspaceSyncPayload, WorkspaceSyncDurabilityStore, } from '../../sync/v3/syncDurabilityStore.js';
10
10
  import { normalizeWorkflowAssignmentSyncRecord } from '../../sync/v3/workflowAssignmentSync.js';
11
- import { createDurableWorkflowRuntimeMutationRouter, resolveWorkflowRuntimeMutationCapability, } from '../../sync/v3/durableWorkflowRuntimeMutationRouter.js';
11
+ import { areWorkflowRuntimeMutationsFenced, createDurableWorkflowRuntimeMutationRouter, resolveWorkflowRuntimeMutationCapability, } from '../../sync/v3/durableWorkflowRuntimeMutationRouter.js';
12
12
  import { parseJsonBody, resolveHttpErrorStatusCode } from './primitives.js';
13
13
  import { requestRuntimeMode } from './shared.js';
14
14
  function writeJson(res, statusCode, payload) {
@@ -94,6 +94,14 @@ export function registerWorkflowRoutes(deps) {
94
94
  const executionMutationGuard = (req, res) => {
95
95
  if (!guard(req, res))
96
96
  return false;
97
+ if (areWorkflowRuntimeMutationsFenced()) {
98
+ writeJson(res, 503, {
99
+ success: false,
100
+ error: 'Workflow execution changes are temporarily paused.',
101
+ code: 'WORKFLOW_RUNTIME_MUTATIONS_FENCED',
102
+ });
103
+ return false;
104
+ }
97
105
  return durableWorkflowHttpEnabled(req) || requireCloudRuntime(res, 'Workflow execution');
98
106
  };
99
107
  const workspaceIdFor = (req) => String(requestWorkspaceId(req) || '').trim() || 'default';
@@ -17,9 +17,11 @@ import { parseJsonBody } from './primitives.js';
17
17
  import { resolveRequestAccess, createSessionTokenCookie, resolveSessionCookieAttributesForRequest, } from '../auth.js';
18
18
  import { isWorkspaceSwitchingEnabledForRuntime } from '../../shared/runtimeContract.js';
19
19
  import { getRouteTimingNow, logSlowBootstrapRoute, requestBootstrapTraceId, resolveErrorStatusCode, serializeJsonWithTiming, setServerTimingHeader } from './shared.js';
20
+ import { WorkspaceDeletionAdmission } from '../workspaceDeletionAdmission.js';
20
21
  // === SECTION: Registration ===
21
22
  export function registerWorkspaceRoutes(deps) {
22
23
  const { addRoute, core, context, ensureAppAccess, auditAuthAction, getObjectStorageClient, ensureWithinDir, sanitizeStorageSegment, sanitizeTaskIdForPath, normalizeDocumentPathInput, } = deps;
24
+ const workspaceDeletionAdmission = new WorkspaceDeletionAdmission();
23
25
  // === SECTION: Storage cleanup helper ===
24
26
  const cleanupDeletedWorkspaceStorage = async (summary) => {
25
27
  const warnings = [];
@@ -231,12 +233,49 @@ export function registerWorkspaceRoutes(deps) {
231
233
  res.end(JSON.stringify({ success: false, error: 'workspaceId is required.', code: 'WORKSPACE_ID_REQUIRED' }));
232
234
  return;
233
235
  }
234
- const resolvedAccess = core.resolveUserAccess(access.userId, targetWorkspaceId, 'member');
236
+ const writeAdmissionError = (decision) => {
237
+ res.setHeader('Retry-After', String(Math.max(1, Math.ceil(decision.retryAfterMs / 1_000))));
238
+ const inProgress = decision.code === 'WORKSPACE_DELETE_IN_PROGRESS';
239
+ res.writeHead(inProgress ? 409 : 429, { 'Content-Type': 'application/json' });
240
+ res.end(JSON.stringify({
241
+ success: false,
242
+ error: inProgress
243
+ ? 'Workspace deletion is already running for this workspace.'
244
+ : 'Workspace deletion was attempted recently. Wait before retrying.',
245
+ code: decision.code,
246
+ retryAfterMs: decision.retryAfterMs,
247
+ }));
248
+ };
249
+ const existingAdmission = workspaceDeletionAdmission.checkExisting(targetWorkspaceId);
250
+ if (existingAdmission) {
251
+ writeAdmissionError(existingAdmission);
252
+ return;
253
+ }
254
+ let resolvedAccess;
255
+ try {
256
+ resolvedAccess = core.resolveUserAccess(access.userId, targetWorkspaceId, 'member');
257
+ }
258
+ catch (error) {
259
+ const statusCode = resolveErrorStatusCode(error, 400);
260
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
261
+ res.end(JSON.stringify({
262
+ success: false,
263
+ error: String(error?.message || 'Unable to resolve workspace access'),
264
+ code: error?.code,
265
+ }));
266
+ return;
267
+ }
235
268
  if (!resolvedAccess || resolvedAccess.role !== 'owner' || resolvedAccess.disabled) {
236
269
  res.writeHead(403, { 'Content-Type': 'application/json' });
237
270
  res.end(JSON.stringify({ success: false, error: 'Only workspace owners can delete this workspace.' }));
238
271
  return;
239
272
  }
273
+ const deletionAdmissionKey = targetWorkspaceId;
274
+ const admission = workspaceDeletionAdmission.acquire(deletionAdmissionKey);
275
+ if (!admission.allowed) {
276
+ writeAdmissionError(admission);
277
+ return;
278
+ }
240
279
  try {
241
280
  const deleted = core.deleteWorkspace({ workspaceId: targetWorkspaceId });
242
281
  const cleanupWarnings = await cleanupDeletedWorkspaceStorage(deleted);
@@ -277,6 +316,9 @@ export function registerWorkspaceRoutes(deps) {
277
316
  code: error?.code
278
317
  }));
279
318
  }
319
+ finally {
320
+ workspaceDeletionAdmission.settle(deletionAdmissionKey);
321
+ }
280
322
  });
281
323
  // === SECTION: Session workspace switch ===
282
324
  // POST /api/taskforce/session/workspace - Switch active workspace in auth session
@@ -27,11 +27,15 @@ import { registerTaskRoutes } from './routes/tasks.js';
27
27
  import { registerWorkspaceRoutes } from './routes/workspaces.js';
28
28
  import { registerAuthRoutes } from './routes/auth.js';
29
29
  import { registerAdminRoutes } from './routes/admin.js';
30
+ import { registerGitHubReviewEvidenceRoutes } from './routes/githubReviewEvidence.js';
31
+ import { registerExecutorPhaseAApprovalRoutes } from './routes/executorPhaseAApprovals.js';
32
+ import { registerExecutorPhaseAIssuerRedemptionRoutes } from './routes/executorPhaseAIssuerRedemptions.js';
30
33
  import { registerResourceRoutes } from './routes/resources.js';
31
34
  import { registerDocumentRoutes } from './routes/documents.js';
32
35
  import { registerDocumentReviewRoutes } from './routes/documentReviews.js';
33
36
  import { registerAnnotatedAttachmentRoutes } from './routes/annotatedAttachments.js';
34
37
  import { registerAgentsRoutes } from './routes/agents.js';
38
+ import { registerModelConnectionsRoutes } from './routes/modelConnections.js';
35
39
  import { registerAgentRolesRoutes } from './routes/agentRoles.js';
36
40
  import { registerAgentSkillsRoutes } from './routes/agentSkills.js';
37
41
  import { registerWorkflowRoutes } from './routes/workflows.js';
@@ -40,6 +44,8 @@ import { createAgentRoleBehaviorReferenceResolver } from '../services/agentRoleR
40
44
  import { registerLocalMcpHealthRoutes } from './routes/localMcpHealth.js';
41
45
  import { registerLocalUpdateRoutes } from './routes/localUpdate.js';
42
46
  import { registerLocalServiceRoutes } from './routes/localService.js';
47
+ import { createGitHubReviewEvidenceRuntime } from '../services/githubReviewEvidenceRuntime.js';
48
+ import { createExecutorPhaseAApprovalRuntime } from '../services/executorPhaseAApprovalRuntime.js';
43
49
  import { escapeHtml } from './routes/primitives.js';
44
50
  import { getRouteEmailConfig, resolvePublicAuthBaseUrl, resolveRuntimeConfigBaseUrl, shouldExposeDevAuthTokens } from './routes/authSupport.js';
45
51
  import { requestHeader, requestRole, requestRuntimeMode, requestUserId, makeAuditAdminAction, makeAuditAuthAction, makeEnsureAdminRole, makeEnsureAppAccess, makeEnsureAuthenticatedUser, makeEnsureCloudPlanData, makeRequestWorkspaceId, makeRequireCloudRuntime, makeResolveAdminRequestActor, makeResolveAuthenticatedUserId, makeResolveAuthenticatedMutationUserId, } from './routes/shared.js';
@@ -1443,6 +1449,51 @@ export function createRoutes(core, context = {}) {
1443
1449
  normalizeDocumentPathInput,
1444
1450
  });
1445
1451
  registerLocalServiceRoutes({ addRoute, core, context: context.localService });
1452
+ const githubReviewEvidence = createGitHubReviewEvidenceRuntime(core);
1453
+ registerGitHubReviewEvidenceRoutes({
1454
+ addRoute,
1455
+ store: githubReviewEvidence.store,
1456
+ configured: githubReviewEvidence.configured,
1457
+ inspectInstallation: (installationId) => githubReviewEvidence.verifier.inspectInstallation(installationId),
1458
+ requestWorkspaceId,
1459
+ requestRole,
1460
+ resolveAuthenticatedUserId,
1461
+ ensureAppAccess,
1462
+ ensureWorkspaceAdminRole,
1463
+ ensureAdminRole,
1464
+ requireCloudRuntime,
1465
+ auditAuthAction,
1466
+ });
1467
+ const executorPhaseAApprovals = createExecutorPhaseAApprovalRuntime(core);
1468
+ registerExecutorPhaseAApprovalRoutes({
1469
+ addRoute,
1470
+ service: executorPhaseAApprovals.service,
1471
+ requireCloudRuntime,
1472
+ ensureAppAccess,
1473
+ resolveHumanSystemAdminActor: (req) => {
1474
+ if (!context.authConfig?.enabled)
1475
+ return null;
1476
+ const access = resolveRequestAccess(req, context.authConfig);
1477
+ if (!access.authenticated || !access.userId || access.userId === 'anonymous')
1478
+ return null;
1479
+ return core.getSystemRole(access.userId) === 'system_admin' ? access.userId : null;
1480
+ },
1481
+ hasActiveWorkspaceMembership: (workspaceId, userId) => core.listWorkspaceUsers(workspaceId).some((membership) => (String(membership.userId || '').trim() === userId
1482
+ && String(membership.status || '').trim().toLowerCase() === 'active'
1483
+ && membership.disabled !== true)),
1484
+ auditAuthAction,
1485
+ workspaceId: executorPhaseAApprovals.policy.workspaceId,
1486
+ allowedOrigin: executorPhaseAApprovals.policy.issuer,
1487
+ performanceEnvironment: resolveDeploymentConfig(process.env).cloudEnvironment === 'performance',
1488
+ });
1489
+ registerExecutorPhaseAIssuerRedemptionRoutes({
1490
+ addRoute,
1491
+ requireCloudRuntime,
1492
+ performanceEnvironment: resolveDeploymentConfig(process.env).cloudEnvironment === 'performance',
1493
+ featureEnabled: String(process.env.TASKFORCE_PHASE_A_ISSUER_REDEMPTION_ENABLED || '').trim().toLowerCase() === 'true',
1494
+ auditAuthAction,
1495
+ workspaceId: executorPhaseAApprovals.policy.workspaceId,
1496
+ });
1446
1497
  registerAdminRoutes({
1447
1498
  addRoute,
1448
1499
  core,
@@ -1452,6 +1503,7 @@ export function createRoutes(core, context = {}) {
1452
1503
  requestRole,
1453
1504
  ensureAppAccess,
1454
1505
  ensureAdminRole,
1506
+ ensureWorkspaceAdminRole,
1455
1507
  ensureCloudPlanData,
1456
1508
  requireCloudRuntime,
1457
1509
  resolveAuthenticatedUserId,
@@ -1565,6 +1617,13 @@ export function createRoutes(core, context = {}) {
1565
1617
  resolveBehaviorReference: createAgentRoleBehaviorReferenceResolver(new AgentRoleStore(core.getDatabaseAdapter(), core.getTenantId()), workspaceId),
1566
1618
  }),
1567
1619
  });
1620
+ registerModelConnectionsRoutes({
1621
+ addRoute,
1622
+ ensureAppAccess,
1623
+ core,
1624
+ resolveAuthenticatedUserId,
1625
+ resolveRuntimeMode: (req) => (context.authConfig?.runtimeMode === 'cloud' ? 'cloud' : requestRuntimeMode(req)),
1626
+ });
1568
1627
  registerAgentRolesRoutes({
1569
1628
  addRoute,
1570
1629
  ensureAppAccess,
@@ -0,0 +1,23 @@
1
+ export declare const WORKSPACE_DELETE_RETRY_COOLDOWN_MS = 30000;
2
+ export type WorkspaceDeletionAdmissionDecision = {
3
+ allowed: true;
4
+ } | {
5
+ allowed: false;
6
+ code: 'WORKSPACE_DELETE_IN_PROGRESS' | 'WORKSPACE_DELETE_RETRY_COOLDOWN';
7
+ retryAfterMs: number;
8
+ };
9
+ /**
10
+ * Serializes destructive workspace cleanup inside one server process and
11
+ * throttles immediate retries after an attempt settles. The caller supplies
12
+ * time so the admission policy can be verified without timers.
13
+ */
14
+ export declare class WorkspaceDeletionAdmission {
15
+ private readonly cooldownMs;
16
+ private readonly entries;
17
+ constructor(cooldownMs?: number);
18
+ checkExisting(key: string, now?: number): Exclude<WorkspaceDeletionAdmissionDecision, {
19
+ allowed: true;
20
+ }> | null;
21
+ acquire(key: string, now?: number): WorkspaceDeletionAdmissionDecision;
22
+ settle(key: string, now?: number): void;
23
+ }
@@ -0,0 +1,50 @@
1
+ export const WORKSPACE_DELETE_RETRY_COOLDOWN_MS = 30_000;
2
+ /**
3
+ * Serializes destructive workspace cleanup inside one server process and
4
+ * throttles immediate retries after an attempt settles. The caller supplies
5
+ * time so the admission policy can be verified without timers.
6
+ */
7
+ export class WorkspaceDeletionAdmission {
8
+ cooldownMs;
9
+ entries = new Map();
10
+ constructor(cooldownMs = WORKSPACE_DELETE_RETRY_COOLDOWN_MS) {
11
+ this.cooldownMs = cooldownMs;
12
+ }
13
+ checkExisting(key, now = Date.now()) {
14
+ let existing = this.entries.get(key);
15
+ if (existing?.state === 'cooldown' && existing.retryAt <= now) {
16
+ this.entries.delete(key);
17
+ existing = undefined;
18
+ }
19
+ if (existing?.state === 'in-flight') {
20
+ return {
21
+ allowed: false,
22
+ code: 'WORKSPACE_DELETE_IN_PROGRESS',
23
+ retryAfterMs: Math.max(1_000, this.cooldownMs),
24
+ };
25
+ }
26
+ if (existing?.state === 'cooldown') {
27
+ return {
28
+ allowed: false,
29
+ code: 'WORKSPACE_DELETE_RETRY_COOLDOWN',
30
+ retryAfterMs: Math.max(1_000, existing.retryAt - now),
31
+ };
32
+ }
33
+ return null;
34
+ }
35
+ acquire(key, now = Date.now()) {
36
+ const existing = this.checkExisting(key, now);
37
+ if (existing)
38
+ return existing;
39
+ this.entries.set(key, { state: 'in-flight' });
40
+ return { allowed: true };
41
+ }
42
+ settle(key, now = Date.now()) {
43
+ if (this.entries.get(key)?.state !== 'in-flight')
44
+ return;
45
+ this.entries.set(key, {
46
+ state: 'cooldown',
47
+ retryAt: now + this.cooldownMs,
48
+ });
49
+ }
50
+ }