@taskforcehq/taskforce 0.3.329 → 0.3.332

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 (363) hide show
  1. package/README.md +7 -2
  2. package/dist/Taskforce.module.css +290 -45
  3. package/dist/components/features/AiProfilesModule.js +3 -5
  4. package/dist/components/features/TaskSettings.js +70 -14
  5. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  6. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  7. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
  8. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
  9. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  10. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  11. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  12. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  13. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  14. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  15. package/dist/components/features/planning/PlanningModule.js +15 -3
  16. package/dist/components/features/planning/planningMetadata.d.ts +10 -0
  17. package/dist/components/features/planning/planningMetadata.js +8 -0
  18. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  19. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  20. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  21. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  22. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  23. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  24. package/dist/components/views/StandaloneLayout.js +62 -27
  25. package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
  26. package/dist/components/views/panels/PlanningDrawer.js +12 -8
  27. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  28. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  29. package/dist/config/envSchema.js +55 -1
  30. package/dist/core/McpTokenService.d.ts +25 -1
  31. package/dist/core/McpTokenService.js +106 -15
  32. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  33. package/dist/core/TaskChecklistCommandService.js +83 -5
  34. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  35. package/dist/core/TaskLifecycleCommandService.js +6 -2
  36. package/dist/core/Taskforce.d.ts +43 -3
  37. package/dist/core/Taskforce.js +158 -7
  38. package/dist/core/types.d.ts +9 -0
  39. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
  40. package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
  41. package/dist/documentReviews/commandService.d.ts +2 -1
  42. package/dist/documentReviews/commandService.js +6 -3
  43. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  44. package/dist/hooks/sync/orchestratorShared.js +2 -0
  45. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  46. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  47. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  48. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  49. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  50. package/dist/hooks/useSyncOrchestrator.js +111 -2
  51. package/dist/hooks/useTaskData.d.ts +31 -1
  52. package/dist/hooks/useTaskData.js +29 -7
  53. package/dist/hooks/useTaskMutations.d.ts +3 -1
  54. package/dist/hooks/useTaskMutations.js +46 -12
  55. package/dist/hooks/useTaskforce.d.ts +2 -0
  56. package/dist/hooks/useTaskforce.js +11 -2
  57. package/dist/mcp/clientRegistry.d.ts +2 -2
  58. package/dist/mcp/clientRegistry.js +1 -1
  59. package/dist/mcp/documentAssetRegistrar.js +9 -6
  60. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  61. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  62. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  63. package/dist/mcp/httpProtocolRouting.d.ts +11 -0
  64. package/dist/mcp/httpProtocolRouting.js +22 -0
  65. package/dist/mcp/localCliHealth.d.ts +2 -2
  66. package/dist/mcp/localCliHealth.js +2 -2
  67. package/dist/mcp/localServiceProxy.d.ts +1 -0
  68. package/dist/mcp/localServiceProxy.js +530 -68
  69. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  70. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  71. package/dist/mcp/runtime.d.ts +54 -79
  72. package/dist/mcp/runtime.js +408 -102
  73. package/dist/mcp/taskPlanningRegistrar.js +25 -6
  74. package/dist/mcp/toolProfiles.d.ts +2 -0
  75. package/dist/mcp/toolProfiles.js +11 -0
  76. package/dist/mcp/toolRegistry.d.ts +1 -0
  77. package/dist/mcp/toolRegistry.js +9 -8
  78. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  79. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  80. package/dist/migrations/taskSchemaMigrations.js +415 -0
  81. package/dist/runtime/appGates.d.ts +2 -1
  82. package/dist/runtime/appGates.js +7 -0
  83. package/dist/server/buildInfo.d.ts +1 -0
  84. package/dist/server/buildInfo.js +5 -1
  85. package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
  86. package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
  87. package/dist/server/index.d.ts +3 -0
  88. package/dist/server/index.js +108 -11
  89. package/dist/server/localDatabaseIdentity.js +4 -1
  90. package/dist/server/localServiceLease.js +2 -1
  91. package/dist/server/localServiceSessions.d.ts +14 -17
  92. package/dist/server/localServiceSessions.js +308 -94
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
  94. package/dist/server/routes/admin.d.ts +4 -0
  95. package/dist/server/routes/admin.js +126 -5
  96. package/dist/server/routes/agents.d.ts +7 -0
  97. package/dist/server/routes/agents.js +277 -24
  98. package/dist/server/routes/billing.js +5 -1
  99. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  100. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  101. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  102. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  103. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  104. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  105. package/dist/server/routes/githubReviewEvidence.js +116 -0
  106. package/dist/server/routes/localService.d.ts +15 -4
  107. package/dist/server/routes/localService.js +136 -40
  108. package/dist/server/routes/modelConnections.d.ts +24 -0
  109. package/dist/server/routes/modelConnections.js +205 -0
  110. package/dist/server/routes/shared.d.ts +22 -0
  111. package/dist/server/routes/shared.js +298 -182
  112. package/dist/server/routes/sync.js +1 -0
  113. package/dist/server/routes/syncAuxRoutes.js +5 -1
  114. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  115. package/dist/server/routes/syncPushRoutes.js +1 -0
  116. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  117. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  118. package/dist/server/routes/tasks.js +21 -2
  119. package/dist/server/routes/workflows.js +9 -1
  120. package/dist/server/routes.js +59 -0
  121. package/dist/service/localServiceCli.d.ts +2 -2
  122. package/dist/service/localServiceCli.js +4 -3
  123. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  124. package/dist/services/codexAppServerModelGateway.js +246 -21
  125. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  126. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  127. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  128. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  129. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  130. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  131. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  132. package/dist/services/executorPhaseAApprovalService.js +609 -0
  133. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  134. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  135. package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
  136. package/dist/services/executorPhaseAIssuerCore.js +402 -0
  137. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  138. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  139. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  140. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  141. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  142. package/dist/services/githubReviewEvidenceService.js +336 -0
  143. package/dist/services/modelGateway.d.ts +7 -0
  144. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  145. package/dist/services/modelProviderConnectionService.js +279 -0
  146. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  147. package/dist/services/modelProviderCredentialHome.js +271 -0
  148. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  149. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  150. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  151. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  152. package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
  153. package/dist/services/taskforceAgentMcpBridge.js +42 -29
  154. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  155. package/dist/shared/adminEdgeProxy.js +94 -0
  156. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  157. package/dist/shared/adminProxySessionCookies.js +86 -0
  158. package/dist/shared/aiProfileColors.d.ts +31 -1
  159. package/dist/shared/aiProfileColors.js +14 -6
  160. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  161. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  162. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  163. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  164. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  165. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  166. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  167. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  168. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  169. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  170. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  171. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  172. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  173. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  174. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  175. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  176. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  177. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  178. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  179. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  180. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  181. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  182. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  183. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  184. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  185. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  186. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  187. package/dist/shared/executorPhaseATiming.js +1 -0
  188. package/dist/shared/planningIdentity.js +1 -1
  189. package/dist/shared/productLogoKeys.d.ts +2 -0
  190. package/dist/shared/productLogoKeys.js +18 -0
  191. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  192. package/dist/shared/taskforceAgentDefinition.js +6 -9
  193. package/dist/shared/taskforceAgentModels.js +7 -3
  194. package/dist/shared/userFeatureGrants.d.ts +4 -0
  195. package/dist/shared/userFeatureGrants.js +7 -0
  196. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  197. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  198. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  199. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  200. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  201. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  202. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  203. package/dist/storage/modelProviderConnectionStore.js +446 -0
  204. package/dist/storage/postgresAdapter.d.ts +4 -0
  205. package/dist/storage/postgresAdapter.js +14 -1
  206. package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
  207. package/dist/storage/postgresRequestDiagnostics.js +15 -2
  208. package/dist/storage/postgresWorker.js +20 -2
  209. package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
  210. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  211. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  212. package/dist/storage/workflowStore.d.ts +2 -0
  213. package/dist/storage/workflowStore.js +39 -2
  214. package/dist/sync/cloudSyncApi.js +4 -2
  215. package/dist/sync/collaborationSyncState.js +5 -0
  216. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  217. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  218. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  219. package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
  220. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
  221. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  222. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  223. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  224. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  225. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  226. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  227. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  228. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  229. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  230. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  231. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  232. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  233. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  234. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  235. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  236. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  237. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  238. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
  239. package/dist/sync/syncApplyHandlers.d.ts +3 -0
  240. package/dist/sync/syncApplyHandlers.js +81 -15
  241. package/dist/sync/syncService.d.ts +15 -0
  242. package/dist/sync/syncService.js +83 -18
  243. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  244. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  245. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  246. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  247. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  248. package/dist/sync/v3/durableOperationReplay.js +18 -0
  249. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  250. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  251. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  252. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  253. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  254. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  255. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  256. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
  257. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
  258. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  259. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  260. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  261. package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
  262. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  263. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  264. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  265. package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
  266. package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
  267. package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
  268. package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
  269. package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
  270. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
  271. package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
  272. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
  273. package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
  274. package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
  275. package/dist/sync/v3/syncDurabilityStore.js +202 -8
  276. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  277. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  278. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  279. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  280. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  281. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  282. package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
  283. package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
  284. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  285. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  286. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  287. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  288. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  289. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
  290. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  291. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  292. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  293. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  294. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  295. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  296. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  297. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  298. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  299. package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
  300. package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
  301. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
  302. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
  303. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  304. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  305. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  306. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  307. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  308. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
  309. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
  310. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  311. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  312. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  313. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  314. package/dist/sync/workspaceRepair.d.ts +5 -2
  315. package/dist/sync/workspaceRepair.js +161 -6
  316. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  317. package/dist/sync/workspaceSyncModel.js +35 -7
  318. package/dist/sync/workspaceSyncState.d.ts +1 -0
  319. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  320. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  321. package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
  322. package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
  323. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
  324. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
  325. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
  326. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
  327. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
  328. package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
  329. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
  330. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
  331. package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
  332. package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
  333. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  334. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
  335. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  336. package/dist/ui/assets/index-DSQINwt9.js +7 -0
  337. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  338. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  339. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  340. package/dist/ui/branding/logos/signature_dark.png +0 -0
  341. package/dist/ui/branding/logos/signature_light.png +0 -0
  342. package/dist/ui/index.html +3 -3
  343. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  344. package/dist/utils/httpSetCookie.d.ts +1 -0
  345. package/dist/utils/httpSetCookie.js +4 -1
  346. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  347. package/dist/utils/localRuntimeUrl.js +14 -0
  348. package/dist/utils/productLogoRegistry.d.ts +2 -0
  349. package/dist/utils/productLogoRegistry.js +36 -0
  350. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  351. package/dist/utils/syncStatusPresentation.js +17 -0
  352. package/dist/utils/taskEvents.d.ts +2 -0
  353. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  354. package/dist/utils/workspaceSyncPresentation.js +23 -17
  355. package/package.json +24 -4
  356. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  357. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  358. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
  359. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  360. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  361. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  362. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  363. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -0,0 +1,140 @@
1
+ import { ExecutorPhaseAApprovalError } from '../../services/executorPhaseAApprovalService.js';
2
+ import { ExecutorPhaseAApprovalConflictError } from '../../storage/executorPhaseAApprovalReceiptStore.js';
3
+ import { EXECUTOR_PHASE_A_ISSUANCE_REQUEST_SCHEMA, EXECUTOR_PHASE_A_MAX_PREFLIGHT_BYTES } from '../../shared/executorPhaseAApprovalReceipt.js';
4
+ import { parseJsonBody } from './primitives.js';
5
+ export const EXECUTOR_PHASE_A_APPROVAL_PAGE_PATH = '/taskforce/admin/executor/phase-a-approval';
6
+ export const EXECUTOR_PHASE_A_APPROVAL_PAGE_SCRIPT_PATH = '/taskforce/admin/executor/phase-a-approval.js';
7
+ export const EXECUTOR_PHASE_A_APPROVAL_ISSUE_PATH = '/api/taskforce/admin/executor/phase-a-approval-receipts';
8
+ function writeJson(res, statusCode, body) {
9
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
10
+ res.end(JSON.stringify(body));
11
+ }
12
+ function isSameOriginJson(req, allowedOrigin) {
13
+ const contentType = String(req.headers['content-type'] || '').split(';')[0].trim().toLowerCase();
14
+ if (contentType !== 'application/json')
15
+ return false;
16
+ const origin = String(req.headers.origin || '').trim();
17
+ if (!origin || origin === 'null')
18
+ return false;
19
+ if (String(req.headers['sec-fetch-site'] || '').trim().toLowerCase() === 'cross-site')
20
+ return false;
21
+ try {
22
+ return origin === allowedOrigin && new URL(origin).origin === allowedOrigin;
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ function renderPage(issuePath) {
29
+ return `<!doctype html>
30
+ <html lang="en">
31
+ <head>
32
+ <meta charset="utf-8" />
33
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
34
+ <title>Phase A Approval</title>
35
+ <style>
36
+ body{margin:0;background:#f5f6f8;color:#17191d;font:15px system-ui,sans-serif}.bar{height:56px;background:#fff;border-bottom:1px solid #dfe2e7;display:flex;align-items:center;padding:0 24px;font-weight:700}.main{max-width:760px;margin:40px auto;padding:0 24px}.panel{background:#fff;border:1px solid #dfe2e7;border-radius:8px;padding:24px}h1{font-size:24px;margin:0 0 24px}label{display:block;font-weight:650;margin-bottom:8px}input{width:100%;box-sizing:border-box;border:1px solid #aeb4bd;padding:12px;border-radius:6px}button{margin-top:20px;background:#176b4d;color:#fff;border:0;border-radius:6px;padding:11px 16px;font-weight:700;cursor:pointer}button:disabled{opacity:.45;cursor:not-allowed}pre{white-space:pre-wrap;background:#f7f8fa;border:1px solid #e2e5e9;padding:12px;min-height:48px;max-height:280px;overflow:auto}
37
+ </style>
38
+ </head>
39
+ <body><div class="bar">Taskforce System Administration</div><main class="main" data-issue-path="${issuePath}" data-request-schema="${EXECUTOR_PHASE_A_ISSUANCE_REQUEST_SCHEMA}"><section class="panel">
40
+ <h1>Phase A Approval</h1>
41
+ <label for="preflight">Canonical preflight JSON</label><input id="preflight" type="file" accept="application/json,.json" />
42
+ <pre id="summary">No preflight selected.</pre><button id="approve" type="button" disabled>Approve and download receipt</button>
43
+ </section></main><script src="${EXECUTOR_PHASE_A_APPROVAL_PAGE_SCRIPT_PATH}" defer></script></body></html>`;
44
+ }
45
+ function renderPageScript() {
46
+ return `const root=document.querySelector('main[data-issue-path]'),file=document.getElementById('preflight'),button=document.getElementById('approve'),summary=document.getElementById('summary');let encoded='';
47
+ file.addEventListener('change',async()=>{button.disabled=true;encoded='';const selected=file.files[0];if(!selected)return;const bytes=new Uint8Array(await selected.arrayBuffer());let binary='';for(const value of bytes)binary+=String.fromCharCode(value);encoded=btoa(binary).replace(/\\+/g,'-').replace(/\\//g,'_').replace(/=+$/,'');try{const value=JSON.parse(new TextDecoder().decode(bytes));summary.textContent=JSON.stringify({runId:value.runId,status:value.status,failures:value.failures,authority:value.approvalContext,target:value.target,source:value.source,budgets:value.budgets,pricing:value.pricing,cleanupInventory:value.logicalEnvelope?.cleanupInventory,collectedAt:value.collectedAt,expiresAt:value.expiresAt},null,2);button.disabled=false}catch{summary.textContent='Invalid JSON.'}});
48
+ button.addEventListener('click',async()=>{button.disabled=true;const response=await fetch(root.dataset.issuePath,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({schema:root.dataset.requestSchema,preflightBase64Url:encoded})});if(!response.ok){let message='Approval failed.';try{message=(await response.json()).error||message}catch{}summary.textContent=message;button.disabled=false;return}const blob=await response.blob(),link=document.createElement('a');link.href=URL.createObjectURL(blob);link.download='taskforce-phase-a-approval-receipt.json';link.click();URL.revokeObjectURL(link.href);summary.textContent='Approval receipt issued.'});`;
49
+ }
50
+ export function registerExecutorPhaseAApprovalRoutes(deps) {
51
+ const authorize = (req, res) => {
52
+ if (!deps.requireCloudRuntime(res, 'Executor Phase A approvals'))
53
+ return null;
54
+ if (!deps.performanceEnvironment) {
55
+ writeJson(res, 404, { error: 'Executor Phase A approvals are available only in the performance environment.' });
56
+ return null;
57
+ }
58
+ if (!deps.ensureAppAccess(req, res))
59
+ return null;
60
+ const actorUserId = String(deps.resolveHumanSystemAdminActor(req) || '').trim();
61
+ if (!actorUserId) {
62
+ deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'human_system_admin_required' }, deps.workspaceId);
63
+ writeJson(res, 403, { error: 'Human system administrator access is required.' });
64
+ return null;
65
+ }
66
+ if (!deps.hasActiveWorkspaceMembership(deps.workspaceId, actorUserId)) {
67
+ deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'active_workspace_membership_required' }, deps.workspaceId);
68
+ writeJson(res, 403, { error: 'Active membership in the Phase A workspace is required.' });
69
+ return null;
70
+ }
71
+ return actorUserId;
72
+ };
73
+ deps.addRoute('GET', EXECUTOR_PHASE_A_APPROVAL_PAGE_PATH, async (req, res) => {
74
+ if (!authorize(req, res))
75
+ return;
76
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });
77
+ res.end(renderPage(EXECUTOR_PHASE_A_APPROVAL_ISSUE_PATH));
78
+ });
79
+ deps.addRoute('GET', EXECUTOR_PHASE_A_APPROVAL_PAGE_SCRIPT_PATH, async (req, res) => {
80
+ if (!authorize(req, res))
81
+ return;
82
+ res.writeHead(200, { 'Content-Type': 'application/javascript; charset=utf-8', 'Cache-Control': 'no-store' });
83
+ res.end(renderPageScript());
84
+ });
85
+ deps.addRoute('POST', EXECUTOR_PHASE_A_APPROVAL_ISSUE_PATH, async (req, res) => {
86
+ const actorUserId = authorize(req, res);
87
+ if (!actorUserId)
88
+ return;
89
+ if (!isSameOriginJson(req, deps.allowedOrigin)) {
90
+ deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'same_origin_json_required' }, deps.workspaceId);
91
+ writeJson(res, 403, { error: 'Same-origin application/json submission is required.' });
92
+ return;
93
+ }
94
+ if (!deps.service) {
95
+ deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'issuer_not_configured' }, deps.workspaceId);
96
+ writeJson(res, 503, { error: 'Phase A approval receipt signing is not configured.' });
97
+ return;
98
+ }
99
+ try {
100
+ const body = await parseJsonBody(req, Math.ceil(EXECUTOR_PHASE_A_MAX_PREFLIGHT_BYTES * 1.4));
101
+ if (!body || typeof body !== 'object' || Array.isArray(body) || Object.keys(body).length !== 2
102
+ || body.schema !== EXECUTOR_PHASE_A_ISSUANCE_REQUEST_SCHEMA || typeof body.preflightBase64Url !== 'string') {
103
+ throw new ExecutorPhaseAApprovalError('Request does not match the Phase A issuance request schema.');
104
+ }
105
+ const encoded = body.preflightBase64Url;
106
+ if (!/^[A-Za-z0-9_-]+$/.test(encoded)) {
107
+ throw new ExecutorPhaseAApprovalError('preflightBase64Url must be unpadded base64url.');
108
+ }
109
+ const preflightBytes = Buffer.from(encoded, 'base64url');
110
+ if (preflightBytes.toString('base64url') !== encoded) {
111
+ throw new ExecutorPhaseAApprovalError('preflightBase64Url is not canonical base64url.');
112
+ }
113
+ const result = deps.service.issue(preflightBytes, actorUserId);
114
+ deps.auditAuthAction(req, result.created ? 'executor.phase-a.approval.issued' : 'executor.phase-a.approval.retried', {
115
+ receiptId: result.receiptId,
116
+ receiptSha256: result.digest,
117
+ }, deps.workspaceId);
118
+ res.writeHead(result.created ? 201 : 200, {
119
+ 'Content-Type': 'application/json',
120
+ 'Content-Disposition': 'attachment; filename="taskforce-phase-a-approval-receipt.json"',
121
+ 'Cache-Control': 'no-store',
122
+ 'X-Taskforce-Receipt-Sha256': result.digest,
123
+ });
124
+ res.end(result.bytes);
125
+ }
126
+ catch (error) {
127
+ const statusCode = error instanceof ExecutorPhaseAApprovalError || error instanceof ExecutorPhaseAApprovalConflictError
128
+ ? error.statusCode
129
+ : Number(error?.statusCode) || 500;
130
+ const code = error instanceof ExecutorPhaseAApprovalError || error instanceof ExecutorPhaseAApprovalConflictError
131
+ ? error.code
132
+ : 'internal_error';
133
+ deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code }, deps.workspaceId);
134
+ writeJson(res, statusCode, {
135
+ error: statusCode >= 500 ? 'Internal server error.' : String(error?.message || 'Approval failed.'),
136
+ code,
137
+ });
138
+ }
139
+ });
140
+ }
@@ -0,0 +1,11 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { RouteHandler } from './primitives.js';
3
+ export interface ExecutorPhaseAIssuerRedemptionRouteDependencies {
4
+ addRoute: (method: string, path: string, handler: RouteHandler) => void;
5
+ requireCloudRuntime: (res: ServerResponse, feature: string) => boolean;
6
+ performanceEnvironment: boolean;
7
+ featureEnabled: boolean;
8
+ auditAuthAction: (req: IncomingMessage, action: string, details: Record<string, unknown>, workspaceIdOverride?: string | null) => void;
9
+ workspaceId: string;
10
+ }
11
+ export declare function registerExecutorPhaseAIssuerRedemptionRoutes(deps: ExecutorPhaseAIssuerRedemptionRouteDependencies): void;
@@ -0,0 +1,24 @@
1
+ import { EXECUTOR_PHASE_A_ISSUER_REDEMPTION_PATH } from '../../shared/executorPhaseAIssuerContracts.js';
2
+ function writeJson(res, statusCode, body) {
3
+ res.writeHead(statusCode, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
4
+ res.end(JSON.stringify(body));
5
+ }
6
+ export function registerExecutorPhaseAIssuerRedemptionRoutes(deps) {
7
+ deps.addRoute('POST', EXECUTOR_PHASE_A_ISSUER_REDEMPTION_PATH, async (req, res) => {
8
+ if (!deps.requireCloudRuntime(res, 'Executor Phase A issuer redemption'))
9
+ return;
10
+ if (!deps.performanceEnvironment || !deps.featureEnabled) {
11
+ writeJson(res, 404, { error: 'Not found.' });
12
+ return;
13
+ }
14
+ // Package 1 deliberately has no integration path. Package 2 must install the
15
+ // independently reviewed pre-Lambda machine-authentication gate first.
16
+ deps.auditAuthAction(req, 'executor.phase-a.issuer-redemption.denied', {
17
+ code: 'broker_preintegration_authentication_not_configured',
18
+ }, deps.workspaceId);
19
+ writeJson(res, 503, {
20
+ error: 'Phase A broker authentication is not configured.',
21
+ code: 'broker_preintegration_authentication_not_configured',
22
+ });
23
+ });
24
+ }
@@ -0,0 +1,19 @@
1
+ import type { IncomingMessage, ServerResponse } from 'http';
2
+ import { type GitHubReviewEvidenceInstallationStore } from '../../storage/githubReviewEvidenceInstallationStore.js';
3
+ import type { GitHubInstallationInspection } from '../../services/githubReviewEvidenceService.js';
4
+ import { type RouteHandler } from './primitives.js';
5
+ export interface GitHubReviewEvidenceRouteDependencies {
6
+ addRoute: (method: string, path: string, handler: RouteHandler) => void;
7
+ store: GitHubReviewEvidenceInstallationStore;
8
+ configured: boolean;
9
+ inspectInstallation: (installationId: string) => Promise<GitHubInstallationInspection>;
10
+ requestWorkspaceId: (req: IncomingMessage) => string;
11
+ requestRole: (req: IncomingMessage) => string;
12
+ resolveAuthenticatedUserId: (req: IncomingMessage) => string;
13
+ ensureAppAccess: (req: IncomingMessage, res: ServerResponse) => boolean;
14
+ ensureWorkspaceAdminRole: (req: IncomingMessage, workspaceIdOverride?: string | null) => boolean;
15
+ ensureAdminRole: (req: IncomingMessage) => boolean;
16
+ requireCloudRuntime: (res: ServerResponse, feature: string) => boolean;
17
+ auditAuthAction: (req: IncomingMessage, action: string, details: Record<string, unknown>, workspaceIdOverride?: string | null) => void;
18
+ }
19
+ export declare function registerGitHubReviewEvidenceRoutes(deps: GitHubReviewEvidenceRouteDependencies): void;
@@ -0,0 +1,116 @@
1
+ import { GitHubReviewEvidenceInstallationConflictError, } from '../../storage/githubReviewEvidenceInstallationStore.js';
2
+ import { GitHubReviewEvidenceError } from '../../services/githubReviewEvidenceService.js';
3
+ import { parseJsonBody } from './primitives.js';
4
+ const SETTINGS_PATH = '/api/taskforce/settings/github-review-evidence/installation';
5
+ function writeJson(res, statusCode, body) {
6
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
7
+ res.end(JSON.stringify(body));
8
+ }
9
+ function publicBinding(binding) {
10
+ if (!binding)
11
+ return null;
12
+ return {
13
+ installationId: binding.installationId,
14
+ accountId: binding.accountId,
15
+ accountLogin: binding.accountLogin,
16
+ accountType: binding.accountType,
17
+ repositorySelection: binding.repositorySelection,
18
+ createdAt: binding.createdAt,
19
+ updatedAt: binding.updatedAt,
20
+ };
21
+ }
22
+ function writeProviderError(res, error) {
23
+ if (error instanceof GitHubReviewEvidenceError) {
24
+ if (error.retryAfterSeconds)
25
+ res.setHeader('Retry-After', String(error.retryAfterSeconds));
26
+ writeJson(res, error.statusCode, { error: error.message, code: error.code });
27
+ return;
28
+ }
29
+ if (error instanceof GitHubReviewEvidenceInstallationConflictError) {
30
+ writeJson(res, error.statusCode, { error: error.message, code: error.code });
31
+ return;
32
+ }
33
+ writeJson(res, 500, { error: 'Internal server error.' });
34
+ }
35
+ export function registerGitHubReviewEvidenceRoutes(deps) {
36
+ const { addRoute, store, configured, inspectInstallation, requestWorkspaceId, requestRole, resolveAuthenticatedUserId, ensureAppAccess, ensureWorkspaceAdminRole, ensureAdminRole, requireCloudRuntime, auditAuthAction, } = deps;
37
+ const authorize = (req, res, systemAdminRequired = false) => {
38
+ if (!ensureAppAccess(req, res))
39
+ return null;
40
+ if (!requireCloudRuntime(res, 'GitHub review evidence'))
41
+ return null;
42
+ const workspaceId = String(requestWorkspaceId(req) || '').trim();
43
+ if (!workspaceId) {
44
+ writeJson(res, 400, { error: 'Workspace ID is required.' });
45
+ return null;
46
+ }
47
+ const actorUserId = String(resolveAuthenticatedUserId(req) || '').trim();
48
+ if (!actorUserId || actorUserId === 'anonymous') {
49
+ writeJson(res, 401, { error: 'Authentication is required.' });
50
+ return null;
51
+ }
52
+ if (systemAdminRequired ? !ensureAdminRole(req) : !ensureWorkspaceAdminRole(req, workspaceId)) {
53
+ writeJson(res, 403, {
54
+ error: systemAdminRequired
55
+ ? 'System administrator access is required.'
56
+ : 'Workspace owner or admin access is required.',
57
+ });
58
+ return null;
59
+ }
60
+ return workspaceId;
61
+ };
62
+ addRoute('GET', SETTINGS_PATH, async (req, res) => {
63
+ const workspaceId = authorize(req, res);
64
+ if (!workspaceId)
65
+ return;
66
+ writeJson(res, 200, { configured, installation: publicBinding(store.get(workspaceId)) });
67
+ });
68
+ addRoute('PUT', SETTINGS_PATH, async (req, res) => {
69
+ const workspaceId = authorize(req, res, true);
70
+ if (!workspaceId)
71
+ return;
72
+ try {
73
+ const body = await parseJsonBody(req, 16 * 1024);
74
+ const installation = await inspectInstallation(String(body?.installationId || '').trim());
75
+ const actorUserId = String(resolveAuthenticatedUserId(req) || '').trim();
76
+ const binding = store.put({
77
+ workspaceId,
78
+ installationId: installation.installationId,
79
+ accountId: installation.accountId,
80
+ accountLogin: installation.accountLogin,
81
+ accountType: installation.accountType,
82
+ repositorySelection: installation.repositorySelection,
83
+ boundByUserId: actorUserId,
84
+ });
85
+ auditAuthAction(req, 'github.review-evidence.installation.bound', {
86
+ installationId: binding.installationId,
87
+ accountId: binding.accountId,
88
+ accountLogin: binding.accountLogin,
89
+ repositorySelection: binding.repositorySelection,
90
+ }, workspaceId);
91
+ writeJson(res, 200, { success: true, installation: publicBinding(binding) });
92
+ }
93
+ catch (error) {
94
+ auditAuthAction(req, 'github.review-evidence.installation.bind-failed', {
95
+ code: error instanceof GitHubReviewEvidenceError || error instanceof GitHubReviewEvidenceInstallationConflictError
96
+ ? error.code
97
+ : 'internal_error',
98
+ }, workspaceId);
99
+ writeProviderError(res, error);
100
+ }
101
+ });
102
+ addRoute('DELETE', SETTINGS_PATH, async (req, res) => {
103
+ const workspaceId = authorize(req, res);
104
+ if (!workspaceId)
105
+ return;
106
+ const existing = store.get(workspaceId);
107
+ const removed = store.delete(workspaceId);
108
+ auditAuthAction(req, 'github.review-evidence.installation.unbound', {
109
+ installationId: existing?.installationId || null,
110
+ accountId: existing?.accountId || null,
111
+ removed,
112
+ actorRole: requestRole(req),
113
+ }, workspaceId);
114
+ writeJson(res, 200, { success: true, removed });
115
+ });
116
+ }
@@ -1,13 +1,24 @@
1
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
1
+ import type { IncomingMessage } from 'http';
2
+ import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
2
3
  import type { TaskforceCore } from '../../core/Taskforce.js';
3
- import { createTaskforceMcpServer } from '../../mcp/runtime.js';
4
+ import { type McpRuntimeFactory, type TaskforceMcpServerOptions } from '../../mcp/runtime.js';
4
5
  import { type LocalServiceRouteContext, type RouteHandler } from './primitives.js';
6
+ export interface LocalMcpRuntimeLease {
7
+ runtime: ReturnType<McpRuntimeFactory>;
8
+ transport: NodeStreamableHTTPServerTransport;
9
+ release(): Promise<void>;
10
+ }
11
+ export type AcquireLocalMcpRuntime = (input: {
12
+ req: IncomingMessage;
13
+ options: TaskforceMcpServerOptions;
14
+ }) => Promise<LocalMcpRuntimeLease>;
5
15
  interface LocalServiceRouteDependencies {
6
16
  addRoute: (method: string, path: string, handler: RouteHandler) => void;
7
17
  core: TaskforceCore;
8
18
  context: LocalServiceRouteContext | undefined;
9
- createMcpServer?: typeof createTaskforceMcpServer;
10
- createMcpTransport?: () => StreamableHTTPServerTransport;
19
+ createMcpServer?: McpRuntimeFactory;
20
+ createMcpTransport?: () => NodeStreamableHTTPServerTransport;
21
+ acquireMcpRuntime?: AcquireLocalMcpRuntime;
11
22
  }
12
23
  export declare function registerLocalServiceRoutes(deps: LocalServiceRouteDependencies): void;
13
24
  export {};
@@ -1,10 +1,15 @@
1
1
  import { createHash, timingSafeEqual } from 'crypto';
2
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
2
+ import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
3
+ import { isJsonContentType } from '@modelcontextprotocol/server';
3
4
  import { parseMcpClientId } from '../../mcp/clientRegistry.js';
4
- import { createTaskforceMcpServer } from '../../mcp/runtime.js';
5
+ import { handleModernMcpHttpRequest, isModernMcpHttpRequest, } from '../../mcp/httpProtocolRouting.js';
6
+ import { createStatelessTaskforceMcpServer, createTaskforceMcpServer, } from '../../mcp/runtime.js';
5
7
  import { MCP_TOOL_PROFILES } from '../../mcp/toolRegistry.js';
6
8
  import { parseJsonBody } from './primitives.js';
9
+ import { setServerTimingHeader } from './shared.js';
7
10
  import { LocalServiceSessionError } from '../localServiceSessions.js';
11
+ import { WorkspaceSyncDurabilityStore } from '../../sync/v3/syncDurabilityStore.js';
12
+ import { assertDurableOperationIdentity, DurableOperationReplayIdentityConflictError, } from '../../sync/v3/durableOperationReplay.js';
8
13
  const API_BASE = '/api/taskforce/local-service/v1';
9
14
  const ALLOWED_SCOPES = new Set(['tasks:read', 'tasks:write', 'workspace:read']);
10
15
  const MAX_REGISTRATION_BODY_BYTES = 32 * 1024;
@@ -16,6 +21,13 @@ function writeJson(res, statusCode, body) {
16
21
  function fail(res, statusCode, error, code) {
17
22
  writeJson(res, statusCode, { error, code });
18
23
  }
24
+ function failMcp(res, statusCode, message) {
25
+ writeJson(res, statusCode, {
26
+ jsonrpc: '2.0',
27
+ error: { code: -32000, message },
28
+ id: null,
29
+ });
30
+ }
19
31
  function isLoopback(req) {
20
32
  const address = String(req.socket.remoteAddress || '').toLowerCase();
21
33
  return address === '127.0.0.1' || address === '::1' || address === '::ffff:127.0.0.1';
@@ -59,7 +71,17 @@ function authenticateSession(req, res, context) {
59
71
  fail(res, 401, 'A valid local service session bearer is required.', 'SESSION_AUTH_REQUIRED');
60
72
  return null;
61
73
  }
62
- const session = context.sessions.authenticate(token);
74
+ let session;
75
+ try {
76
+ session = context.sessions.authenticate(token);
77
+ }
78
+ catch (error) {
79
+ if (error instanceof LocalServiceSessionError) {
80
+ fail(res, error.statusCode, error.message, error.code);
81
+ return null;
82
+ }
83
+ throw error;
84
+ }
63
85
  if (!session) {
64
86
  fail(res, 401, 'The local service session is invalid or expired.', 'SESSION_INVALID');
65
87
  return null;
@@ -110,42 +132,60 @@ function normalizeRegistration(body, context) {
110
132
  profileToken: profileToken || null,
111
133
  };
112
134
  }
113
- function lookupBoundOperation(core, context, session, operationId, req) {
135
+ function lookupDurableOperation(core, context, session, operationId, req) {
114
136
  const url = new URL(req.url || '/', 'http://127.0.0.1');
115
137
  const expectedMutationKind = String(url.searchParams.get('mutationKind') || '').trim() || null;
116
138
  const expectedPayloadFingerprint = String(url.searchParams.get('payloadFingerprint') || '').trim() || null;
117
- const binding = context.sessions.getOperationBinding(session.id, operationId, {
118
- mutationKind: expectedMutationKind,
119
- payloadFingerprint: expectedPayloadFingerprint,
139
+ const row = new WorkspaceSyncDurabilityStore(core.getDatabaseAdapter()).readOutboxOperationLookup({
140
+ tenantId: core.getTenantId(),
141
+ workspaceId: session.workspaceId,
142
+ clientId: context.operationClientId,
143
+ operationId,
120
144
  });
121
- if (!binding)
122
- return null;
123
- const row = core.getDatabaseAdapter().prepare(`
124
- SELECT status, authoritative_response_json, created_at,
125
- mutation_kind, payload_fingerprint
126
- FROM workspace_sync_outbox
127
- WHERE tenant_id = ?
128
- AND workspace_id = ?
129
- AND client_id = ?
130
- AND operation_id = ?
131
- LIMIT 1
132
- `).get(core.getTenantId(), session.workspaceId, context.operationClientId, operationId);
133
145
  if (!row)
134
146
  return null;
135
- const responseJson = typeof row.authoritative_response_json === 'string'
136
- ? row.authoritative_response_json
137
- : null;
147
+ try {
148
+ assertDurableOperationIdentity({
149
+ operationId: row.operationId,
150
+ domain: row.domain,
151
+ entityId: row.entityId,
152
+ mutationKind: row.mutationKind,
153
+ payloadFingerprint: row.payloadFingerprint,
154
+ }, {
155
+ operationId,
156
+ domain: row.domain,
157
+ entityId: row.entityId,
158
+ mutationKind: expectedMutationKind || row.mutationKind,
159
+ payloadFingerprint: expectedPayloadFingerprint || row.payloadFingerprint,
160
+ });
161
+ }
162
+ catch (error) {
163
+ if (!(error instanceof DurableOperationReplayIdentityConflictError))
164
+ throw error;
165
+ throw new LocalServiceSessionError('Operation identity is assigned to a different durable mutation.', 409, 'OPERATION_IDENTITY_CONFLICT');
166
+ }
167
+ const responseJson = row.authoritativeResponseJson;
138
168
  if (responseJson && Buffer.byteLength(responseJson, 'utf8') > MAX_MCP_BODY_BYTES) {
139
169
  throw new LocalServiceSessionError('Operation response exceeds the local service limit.', 500, 'OPERATION_RESPONSE_INVALID');
140
170
  }
171
+ let response = null;
172
+ if (responseJson) {
173
+ try {
174
+ response = JSON.parse(responseJson);
175
+ }
176
+ catch {
177
+ throw new LocalServiceSessionError('Operation response is invalid.', 500, 'OPERATION_RESPONSE_INVALID');
178
+ }
179
+ }
141
180
  return {
142
181
  operationId,
143
182
  status: row.status,
144
- createdAt: row.created_at,
145
- mutationKind: row.mutation_kind,
146
- payloadFingerprint: binding.payloadFingerprint,
147
- durablePayloadFingerprint: row.payload_fingerprint,
148
- response: responseJson ? JSON.parse(responseJson) : null,
183
+ createdAt: row.createdAt,
184
+ mutationKind: row.mutationKind,
185
+ payloadFingerprint: row.payloadFingerprint,
186
+ domain: row.domain,
187
+ entityId: row.entityId,
188
+ response,
149
189
  };
150
190
  }
151
191
  function auditShutdown(core, context, input) {
@@ -255,7 +295,7 @@ export function registerLocalServiceRoutes(deps) {
255
295
  if (!session)
256
296
  return;
257
297
  try {
258
- const operation = lookupBoundOperation(deps.core, context, session, params.operationId, req);
298
+ const operation = lookupDurableOperation(deps.core, context, session, params.operationId, req);
259
299
  if (!operation) {
260
300
  fail(res, 404, 'Operation not found.', 'OPERATION_NOT_FOUND');
261
301
  return;
@@ -343,21 +383,34 @@ export function registerLocalServiceRoutes(deps) {
343
383
  deps.addRoute('POST', '/mcp', async (req, res) => {
344
384
  if (!guardLocalRequest(req, res))
345
385
  return;
386
+ const authStartedAtMs = Date.now();
346
387
  const session = authenticateSession(req, res, context);
347
388
  if (!session)
348
389
  return;
390
+ if (!isJsonContentType(header(req, 'content-type'))) {
391
+ failMcp(res, 415, 'Unsupported Media Type: Content-Type must be application/json');
392
+ return;
393
+ }
394
+ const authMs = Date.now() - authStartedAtMs;
349
395
  let runtime = null;
396
+ let runtimeLease = null;
397
+ let bodyParseMs = 0;
398
+ let runtimeConstructionMs = 0;
399
+ let transportConnectMs = 0;
350
400
  let requestStarted = false;
351
401
  let unregisterCancellation = () => { };
352
402
  let resolveCancellation = () => { };
353
403
  const cancellation = new Promise((resolve) => { resolveCancellation = resolve; });
354
404
  try {
405
+ const bodyParseStartedAtMs = Date.now();
355
406
  const body = await parseJsonBody(req, MAX_MCP_BODY_BYTES);
407
+ bodyParseMs = Date.now() - bodyParseStartedAtMs;
408
+ const modernProtocolRequest = await isModernMcpHttpRequest(req, body);
356
409
  const cancellationId = body?.method === 'notifications/cancelled'
357
410
  && (typeof body?.params?.requestId === 'string' || typeof body?.params?.requestId === 'number')
358
411
  ? body.params.requestId
359
412
  : null;
360
- if (cancellationId !== null) {
413
+ if (cancellationId !== null && !modernProtocolRequest) {
361
414
  const correlationId = requestCorrelation(req, 'x-taskforce-mcp-cancel-correlation');
362
415
  if (correlationId)
363
416
  context.sessions.cancelRequest(session.id, correlationId);
@@ -377,7 +430,8 @@ export function registerLocalServiceRoutes(deps) {
377
430
  }
378
431
  if (cancelled)
379
432
  return;
380
- runtime = (deps.createMcpServer || createTaskforceMcpServer)({
433
+ const runtimeStartedAtMs = Date.now();
434
+ const runtimeOptions = {
381
435
  projectRoot: deps.core.getPaths().projectRoot,
382
436
  tenantId: deps.core.getTenantId(),
383
437
  workspaceId: session.workspaceId,
@@ -386,8 +440,6 @@ export function registerLocalServiceRoutes(deps) {
386
440
  logStartup: false,
387
441
  runtimeMode: 'local',
388
442
  operationIdentityScope: {
389
- generation: context.generation,
390
- sessionId: session.id,
391
443
  connectionInstance: session.connectionInstance,
392
444
  },
393
445
  toolProfile: session.toolProfile,
@@ -404,18 +456,59 @@ export function registerLocalServiceRoutes(deps) {
404
456
  userAgent: header(req, 'user-agent').trim() || null,
405
457
  },
406
458
  onAiProfileBound: (profileId) => context.sessions.bindAiProfile(session.id, profileId),
407
- onOperationAccepted: (operation) => context.sessions.recordOperation({
408
- sessionId: session.id,
409
- ...operation,
410
- }),
411
- });
412
- const transport = deps.createMcpTransport?.() || new StreamableHTTPServerTransport({
459
+ };
460
+ if (modernProtocolRequest) {
461
+ const handling = handleModernMcpHttpRequest({
462
+ req,
463
+ res,
464
+ parsedBody: body,
465
+ factory: ({ era }) => {
466
+ const constructionStartedAtMs = Date.now();
467
+ const modernRuntime = createStatelessTaskforceMcpServer({ ...runtimeOptions, protocolEra: era }, deps.createMcpServer || createTaskforceMcpServer);
468
+ runtimeConstructionMs = Date.now() - constructionStartedAtMs;
469
+ if (!res.headersSent) {
470
+ setServerTimingHeader(res, [
471
+ { name: 'auth', durationMs: authMs },
472
+ { name: 'body-parse', durationMs: bodyParseMs },
473
+ { name: 'runtime', durationMs: runtimeConstructionMs },
474
+ ]);
475
+ }
476
+ return modernRuntime.server;
477
+ },
478
+ });
479
+ await Promise.race([handling, cancellation]);
480
+ if (cancelled)
481
+ void handling.catch(() => undefined);
482
+ if (cancellationId !== null && res.statusCode === 202) {
483
+ const cancellationCorrelation = requestCorrelation(req, 'x-taskforce-mcp-cancel-correlation');
484
+ if (cancellationCorrelation) {
485
+ context.sessions.cancelRequest(session.id, cancellationCorrelation);
486
+ }
487
+ }
488
+ return;
489
+ }
490
+ runtimeLease = deps.acquireMcpRuntime
491
+ ? await deps.acquireMcpRuntime({ req, options: runtimeOptions })
492
+ : null;
493
+ runtime = runtimeLease?.runtime
494
+ || createStatelessTaskforceMcpServer(runtimeOptions, deps.createMcpServer || createTaskforceMcpServer);
495
+ runtimeConstructionMs = Date.now() - runtimeStartedAtMs;
496
+ const transport = runtimeLease?.transport || deps.createMcpTransport?.() || new NodeStreamableHTTPServerTransport({
413
497
  sessionIdGenerator: undefined,
414
498
  enableJsonResponse: true,
415
499
  });
416
- await runtime.server.connect(transport);
500
+ const transportStartedAtMs = Date.now();
501
+ if (!runtimeLease)
502
+ await runtime.server.connect(transport);
503
+ transportConnectMs = Date.now() - transportStartedAtMs;
417
504
  if (cancelled)
418
505
  return;
506
+ setServerTimingHeader(res, [
507
+ { name: 'auth', durationMs: authMs },
508
+ { name: 'body-parse', durationMs: bodyParseMs },
509
+ { name: 'runtime', durationMs: runtimeConstructionMs },
510
+ { name: 'transport-connect', durationMs: transportConnectMs },
511
+ ]);
419
512
  const handling = transport.handleRequest(req, res, body);
420
513
  await Promise.race([handling, cancellation]);
421
514
  if (cancelled)
@@ -430,7 +523,10 @@ export function registerLocalServiceRoutes(deps) {
430
523
  }
431
524
  finally {
432
525
  unregisterCancellation();
433
- await runtime?.server.close().catch(() => undefined);
526
+ if (runtimeLease)
527
+ await runtimeLease.release().catch(() => undefined);
528
+ else
529
+ await runtime?.server.close().catch(() => undefined);
434
530
  if (requestStarted)
435
531
  context.sessions.endRequest(session.id);
436
532
  }
@@ -0,0 +1,24 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { TaskforceCore } from '../../core/Taskforce.js';
3
+ import { ModelProviderConnectionService, type ModelProviderConnectionLifecycleHandlers } from '../../services/modelProviderConnectionService.js';
4
+ import { CodexDeviceCodeLoginManager } from '../../services/codexDeviceCodeLoginManager.js';
5
+ import { type RouteHandler } from './primitives.js';
6
+ type ConnectionService = Pick<ModelProviderConnectionService, 'create' | 'list' | 'get' | 'rename' | 'verify' | 'refresh' | 'disconnect' | 'cleanup'>;
7
+ type DeviceCodeLoginManager = Pick<CodexDeviceCodeLoginManager, 'start' | 'get' | 'cancel'>;
8
+ export interface ModelConnectionsRouteDependencies {
9
+ addRoute: (method: string, path: string, handler: RouteHandler) => void;
10
+ ensureAppAccess: (req: IncomingMessage, res: ServerResponse) => boolean;
11
+ resolveAuthenticatedUserId: (req: IncomingMessage) => string | null;
12
+ resolveRuntimeMode: (req: IncomingMessage) => 'local' | 'cloud';
13
+ core?: TaskforceCore;
14
+ service?: ConnectionService;
15
+ loginManager?: DeviceCodeLoginManager;
16
+ credentialStoragePath?: string | null;
17
+ lifecycleHandlers?: Array<{
18
+ providerKey: string;
19
+ authenticationType: string;
20
+ lifecycle: ModelProviderConnectionLifecycleHandlers;
21
+ }>;
22
+ }
23
+ export declare function registerModelConnectionsRoutes(deps: ModelConnectionsRouteDependencies): void;
24
+ export {};