@taskforcehq/taskforce 0.3.329 → 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 (321) hide show
  1. package/dist/Taskforce.module.css +290 -45
  2. package/dist/components/features/AiProfilesModule.js +3 -5
  3. package/dist/components/features/TaskSettings.js +70 -14
  4. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  5. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  6. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  7. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  8. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  9. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  10. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  11. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  12. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  13. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  14. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  15. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  16. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  17. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  18. package/dist/components/views/StandaloneLayout.js +27 -26
  19. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  20. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  21. package/dist/config/envSchema.js +48 -1
  22. package/dist/core/McpTokenService.d.ts +23 -1
  23. package/dist/core/McpTokenService.js +93 -10
  24. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  25. package/dist/core/TaskChecklistCommandService.js +83 -5
  26. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  27. package/dist/core/TaskLifecycleCommandService.js +6 -2
  28. package/dist/core/Taskforce.d.ts +32 -0
  29. package/dist/core/Taskforce.js +125 -4
  30. package/dist/core/types.d.ts +8 -0
  31. package/dist/documentReviews/commandService.d.ts +2 -1
  32. package/dist/documentReviews/commandService.js +6 -3
  33. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  34. package/dist/hooks/sync/orchestratorShared.js +2 -0
  35. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  36. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  37. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  38. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  39. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  40. package/dist/hooks/useSyncOrchestrator.js +111 -2
  41. package/dist/hooks/useTaskData.d.ts +31 -1
  42. package/dist/hooks/useTaskData.js +29 -7
  43. package/dist/hooks/useTaskMutations.d.ts +3 -1
  44. package/dist/hooks/useTaskMutations.js +46 -12
  45. package/dist/hooks/useTaskforce.d.ts +2 -0
  46. package/dist/hooks/useTaskforce.js +11 -2
  47. package/dist/mcp/clientRegistry.d.ts +2 -2
  48. package/dist/mcp/clientRegistry.js +1 -1
  49. package/dist/mcp/documentAssetRegistrar.js +9 -6
  50. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  51. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  52. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  53. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  54. package/dist/mcp/httpProtocolRouting.js +19 -0
  55. package/dist/mcp/localCliHealth.d.ts +2 -2
  56. package/dist/mcp/localCliHealth.js +2 -2
  57. package/dist/mcp/localServiceProxy.d.ts +1 -0
  58. package/dist/mcp/localServiceProxy.js +530 -68
  59. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  60. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  61. package/dist/mcp/runtime.d.ts +54 -79
  62. package/dist/mcp/runtime.js +384 -97
  63. package/dist/mcp/taskPlanningRegistrar.js +23 -4
  64. package/dist/mcp/toolProfiles.d.ts +2 -0
  65. package/dist/mcp/toolProfiles.js +10 -0
  66. package/dist/mcp/toolRegistry.d.ts +1 -0
  67. package/dist/mcp/toolRegistry.js +1 -0
  68. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  69. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  70. package/dist/migrations/taskSchemaMigrations.js +415 -0
  71. package/dist/runtime/appGates.d.ts +2 -1
  72. package/dist/runtime/appGates.js +7 -0
  73. package/dist/server/index.d.ts +3 -0
  74. package/dist/server/index.js +108 -11
  75. package/dist/server/localDatabaseIdentity.js +4 -1
  76. package/dist/server/localServiceLease.js +2 -1
  77. package/dist/server/localServiceSessions.d.ts +14 -17
  78. package/dist/server/localServiceSessions.js +308 -94
  79. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
  80. package/dist/server/routes/admin.d.ts +4 -0
  81. package/dist/server/routes/admin.js +112 -3
  82. package/dist/server/routes/agents.d.ts +7 -0
  83. package/dist/server/routes/agents.js +277 -24
  84. package/dist/server/routes/billing.js +5 -1
  85. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  86. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  87. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  88. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  89. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  90. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  91. package/dist/server/routes/githubReviewEvidence.js +116 -0
  92. package/dist/server/routes/localService.d.ts +15 -4
  93. package/dist/server/routes/localService.js +136 -40
  94. package/dist/server/routes/modelConnections.d.ts +24 -0
  95. package/dist/server/routes/modelConnections.js +205 -0
  96. package/dist/server/routes/shared.d.ts +19 -0
  97. package/dist/server/routes/shared.js +95 -19
  98. package/dist/server/routes/sync.js +1 -0
  99. package/dist/server/routes/syncAuxRoutes.js +5 -1
  100. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  101. package/dist/server/routes/syncPushRoutes.js +1 -0
  102. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  103. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  104. package/dist/server/routes/tasks.js +21 -2
  105. package/dist/server/routes/workflows.js +9 -1
  106. package/dist/server/routes.js +59 -0
  107. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  108. package/dist/services/codexAppServerModelGateway.js +246 -21
  109. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  110. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  111. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  112. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  113. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  114. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  115. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  116. package/dist/services/executorPhaseAApprovalService.js +609 -0
  117. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  118. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  119. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  120. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  121. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  122. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  123. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  124. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  125. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  126. package/dist/services/githubReviewEvidenceService.js +336 -0
  127. package/dist/services/modelGateway.d.ts +7 -0
  128. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  129. package/dist/services/modelProviderConnectionService.js +279 -0
  130. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  131. package/dist/services/modelProviderCredentialHome.js +271 -0
  132. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  133. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  134. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  135. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  136. package/dist/services/taskforceAgentMcpBridge.d.ts +1 -1
  137. package/dist/services/taskforceAgentMcpBridge.js +7 -24
  138. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  139. package/dist/shared/adminEdgeProxy.js +94 -0
  140. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  141. package/dist/shared/adminProxySessionCookies.js +86 -0
  142. package/dist/shared/aiProfileColors.d.ts +31 -1
  143. package/dist/shared/aiProfileColors.js +14 -6
  144. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  145. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  146. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  147. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  148. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  149. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  150. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  151. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  152. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  153. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  154. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  155. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  156. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  157. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  158. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  159. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  160. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  161. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  162. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  163. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  164. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  165. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  166. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  167. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  168. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  169. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  170. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  171. package/dist/shared/executorPhaseATiming.js +1 -0
  172. package/dist/shared/planningIdentity.js +1 -1
  173. package/dist/shared/productLogoKeys.d.ts +2 -0
  174. package/dist/shared/productLogoKeys.js +18 -0
  175. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  176. package/dist/shared/taskforceAgentDefinition.js +6 -9
  177. package/dist/shared/taskforceAgentModels.js +7 -3
  178. package/dist/shared/userFeatureGrants.d.ts +4 -0
  179. package/dist/shared/userFeatureGrants.js +7 -0
  180. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  181. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  182. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  183. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  184. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  185. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  186. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  187. package/dist/storage/modelProviderConnectionStore.js +446 -0
  188. package/dist/storage/postgresAdapter.d.ts +4 -0
  189. package/dist/storage/postgresAdapter.js +11 -0
  190. package/dist/storage/postgresWorker.js +9 -1
  191. package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
  192. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  193. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  194. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  195. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  196. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  197. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  198. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  199. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  200. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  201. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  202. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  203. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  204. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  205. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  206. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  207. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  208. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  209. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  210. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  211. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  212. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  213. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  214. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  215. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  216. package/dist/sync/syncApplyHandlers.js +10 -1
  217. package/dist/sync/syncService.d.ts +15 -0
  218. package/dist/sync/syncService.js +83 -18
  219. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  220. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  221. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  222. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  223. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  224. package/dist/sync/v3/durableOperationReplay.js +18 -0
  225. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  226. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  227. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  228. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  229. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  230. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  231. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  232. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  233. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  234. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  235. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  236. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  237. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  238. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  239. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  240. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +8 -0
  241. package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
  242. package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
  243. package/dist/sync/v3/syncDurabilityStore.js +168 -2
  244. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  245. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  246. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  247. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  248. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  249. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  250. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  251. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  252. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  253. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  254. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  255. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  256. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  257. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  258. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  259. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  260. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  261. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  262. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  263. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  264. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  265. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  266. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  267. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  268. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  269. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  270. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  271. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  272. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  273. package/dist/sync/workspaceRepair.d.ts +5 -2
  274. package/dist/sync/workspaceRepair.js +161 -6
  275. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  276. package/dist/sync/workspaceSyncModel.js +35 -7
  277. package/dist/sync/workspaceSyncState.d.ts +1 -0
  278. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  279. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  280. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  281. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  282. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
  283. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  284. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
  285. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  286. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  287. package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
  288. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
  289. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
  290. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  291. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  292. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  293. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  294. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  295. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  296. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  297. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  298. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  299. package/dist/ui/branding/logos/signature_dark.png +0 -0
  300. package/dist/ui/branding/logos/signature_light.png +0 -0
  301. package/dist/ui/index.html +3 -3
  302. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  303. package/dist/utils/httpSetCookie.d.ts +1 -0
  304. package/dist/utils/httpSetCookie.js +4 -1
  305. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  306. package/dist/utils/localRuntimeUrl.js +14 -0
  307. package/dist/utils/productLogoRegistry.d.ts +2 -0
  308. package/dist/utils/productLogoRegistry.js +36 -0
  309. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  310. package/dist/utils/syncStatusPresentation.js +17 -0
  311. package/dist/utils/taskEvents.d.ts +2 -0
  312. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  313. package/dist/utils/workspaceSyncPresentation.js +23 -17
  314. package/package.json +22 -4
  315. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  316. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  317. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  318. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  319. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  320. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  321. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -1,18 +1,28 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState } from 'react';
3
- import { AlertTriangle, ChevronDown, Copy, Loader2, RefreshCw } from 'lucide-react';
3
+ import { AlertTriangle, ChevronDown, Copy, Loader2 } from 'lucide-react';
4
4
  import { Modal } from '../../../ui/Modal';
5
5
  import modalStyles from '../../../ui/Modal.module.css';
6
6
  import syncStatusStyles from '../../SyncStatusModal.module.css';
7
7
  import styles from '../../../../Taskforce.module.css';
8
8
  import { isWorkspaceSyncAuthenticationError } from '../../../../utils/workspaceSyncPresentation';
9
- export function SyncStatusModal({ isOpen, theme, currentWorkspaceLabel, syncStatus, syncStatusMeta, workspaceCloudSyncEnabled, syncControlBusy, canManageWorkspaceSync, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncRepairBusy, referenceMismatchCount, syncStageLabel, workspaceSyncPendingChanges, incomingCloudChanges, formattedLastSyncTime, formattedLastPullTime, formattedLastPushTime, syncLastError, activeReferenceMismatchSummaries, syncDiagnosticsSummary, syncEventRows, syncEventsListRef, workspaceSyncRepairQueued, workspaceSyncBusy, workspaceSyncCopied, coordinatorOwnershipMode, coordinatorOwnershipTransferBusy, coordinatorOwnershipTransferDisabled, onClose, onToggleWorkspaceSync, onRepairSync, onCopyReport, onRetrySync, onTransferCoordinatorOwnership, }) {
9
+ export function SyncStatusModal({ isOpen, theme, currentWorkspaceLabel, syncStatus, syncStatusMeta, workspaceCloudSyncEnabled, syncControlBusy, syncControlIntent, canManageWorkspaceSync, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncRepairBusy, referenceMismatchCount, syncStageLabel, workspaceSyncPendingChanges, incomingCloudChanges, formattedLastSyncTime, formattedLastPullTime, formattedLastPushTime, syncLastError, activeReferenceMismatchSummaries, syncDiagnosticsSummary, syncEventRows, syncEventsListRef, workspaceSyncRepairQueued, workspaceSyncBusy, workspaceSyncCopied, coordinatorOwnershipMode, coordinatorOwnershipTransferBusy, coordinatorOwnershipTransferDisabled, onClose, onToggleWorkspaceSync, onRepairSync, onCopyReport, onTransferCoordinatorOwnership, }) {
10
10
  const [eventFilter, setEventFilter] = useState('all');
11
11
  useEffect(() => {
12
12
  if (isOpen)
13
13
  setEventFilter('all');
14
14
  }, [isOpen]);
15
15
  const needsAttention = syncStatus === 'attention';
16
+ const displayedSyncEnabled = syncControlIntent === 'enabling'
17
+ ? true
18
+ : syncControlIntent === 'disabling'
19
+ ? false
20
+ : workspaceCloudSyncEnabled;
21
+ const syncControlTransitionLabel = syncControlIntent === 'enabling'
22
+ ? 'Turning on…'
23
+ : syncControlIntent === 'disabling'
24
+ ? 'Turning off…'
25
+ : null;
16
26
  const activeIssue = workspaceSyncRepairBusy
17
27
  ? referenceMismatchCount > 0
18
28
  ? `Repair is reconciling cloud state, including ${referenceMismatchCount} reference mismatch${referenceMismatchCount === 1 ? '' : 'es'}.`
@@ -26,58 +36,43 @@ export function SyncStatusModal({ isOpen, theme, currentWorkspaceLabel, syncStat
26
36
  const coordinatorOwnedByOtherProcess = /\banother local taskforce process owns workspace synchronization\b/i.test(syncLastError);
27
37
  const coordinatorAuthenticationRequired = isWorkspaceSyncAuthenticationError(syncLastError);
28
38
  const repairActionAvailable = workspaceCloudSyncEnabled
39
+ && syncStatus !== 'checking'
29
40
  && !coordinatorOwnedByOtherProcess
30
41
  && !coordinatorAuthenticationRequired
31
42
  && (needsAttention
32
43
  || workspaceSyncBusy
33
44
  || workspaceSyncRepairBusy
34
45
  || workspaceSyncRepairQueued);
35
- const retryActionAvailable = workspaceCloudSyncEnabled
36
- && !coordinatorOwnedByOtherProcess
37
- && !coordinatorAuthenticationRequired
38
- && (workspaceSyncBusy
39
- || needsAttention
40
- || /\bpress sync\b/i.test(workspaceSyncRecommendedAction));
41
46
  const visibleEventRows = useMemo(() => eventFilter === 'issues'
42
47
  ? syncEventRows.filter((row) => row.tone === 'error')
43
48
  : syncEventRows, [eventFilter, syncEventRows]);
44
- const footer = (_jsxs("div", { className: syncStatusStyles.syncStatusFooter, children: [_jsxs("button", { className: styles.cancelBtn, onClick: onCopyReport, title: "Copy the current sync manager report for support or AI troubleshooting.", children: [_jsx(Copy, { size: 14 }), _jsx("span", { children: workspaceSyncCopied ? 'Copied' : 'Copy Report' })] }), _jsxs("div", { className: syncStatusStyles.syncStatusFooterPrimary, children: [_jsx("button", { className: styles.cancelBtn, onClick: onRepairSync, disabled: !repairActionAvailable
45
- || workspaceSyncRepairBusy
46
- || workspaceSyncRepairQueued, title: workspaceSyncRepairBusy
47
- ? 'Repair is running now.'
48
- : workspaceSyncRepairQueued
49
- ? 'Repair is queued and will start when the current sync finishes.'
50
- : !workspaceCloudSyncEnabled
51
- ? 'Turn on workspace sync before running Repair.'
52
- : coordinatorOwnedByOtherProcess
53
- ? 'Repair is unavailable in this process. Use the Taskforce process that owns workspace synchronization.'
54
- : coordinatorAuthenticationRequired
55
- ? 'Sign out and sign back in before running Repair.'
56
- : workspaceSyncBusy
57
- ? 'Queue a repair to start automatically when the current sync finishes.'
58
- : !repairActionAvailable
59
- ? 'Repair is available when sync needs attention.'
60
- : 'Advanced recovery: clear the saved pull cursor and re-fetch cloud state from the beginning.', children: workspaceSyncRepairBusy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 14, className: styles.spinner }), "Repairing..."] })) : workspaceSyncRepairQueued ? ('Repair Queued') : ('Repair') }), _jsx("button", { className: styles.submitBtn, onClick: onRetrySync, disabled: !retryActionAvailable || workspaceSyncBusy, title: workspaceSyncBusy
61
- ? 'A sync request is already running.'
49
+ const footer = (_jsxs("div", { className: syncStatusStyles.syncStatusFooter, children: [_jsxs("button", { className: styles.cancelBtn, onClick: onCopyReport, title: "Copy the current sync manager report for support or AI troubleshooting.", children: [_jsx(Copy, { size: 14 }), _jsx("span", { children: workspaceSyncCopied ? 'Copied' : 'Copy Report' })] }), _jsx("div", { className: syncStatusStyles.syncStatusFooterPrimary, children: _jsx("button", { className: styles.cancelBtn, onClick: onRepairSync, disabled: !repairActionAvailable
50
+ || workspaceSyncRepairBusy
51
+ || workspaceSyncRepairQueued, title: workspaceSyncRepairBusy
52
+ ? 'Repair is running now.'
53
+ : workspaceSyncRepairQueued
54
+ ? 'Repair is queued and will start when the current sync finishes.'
62
55
  : !workspaceCloudSyncEnabled
63
- ? 'Turn on workspace sync before retrying.'
56
+ ? 'Turn on workspace sync before running Repair.'
64
57
  : coordinatorOwnedByOtherProcess
65
- ? 'Retry is unavailable in this process. Use the Taskforce process that owns workspace synchronization.'
58
+ ? 'Repair is unavailable in this process. Use the Taskforce process that owns workspace synchronization.'
66
59
  : coordinatorAuthenticationRequired
67
- ? 'Sign out and sign back in before retrying sync.'
68
- : !retryActionAvailable
69
- ? 'No retry is currently needed.'
70
- : 'Retry workspace synchronization now.', children: workspaceSyncBusy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 14, className: styles.spinner }), "Syncing..."] })) : (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { size: 14 }), "Retry now"] })) })] })] }));
60
+ ? 'Sign out and sign back in before running Repair.'
61
+ : workspaceSyncBusy
62
+ ? 'Queue a repair to start automatically when the current sync finishes.'
63
+ : !repairActionAvailable
64
+ ? 'Repair is available when sync needs attention.'
65
+ : 'Advanced recovery: clear the saved pull cursor and re-fetch cloud state from the beginning.', children: workspaceSyncRepairBusy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 14, className: styles.spinner }), "Repairing..."] })) : workspaceSyncRepairQueued ? ('Repair Queued') : ('Repair') }) })] }));
71
66
  return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: "Sync Manager", size: "mdWide", theme: theme, draggable: true, className: syncStatusStyles.syncStatusOverlay, footer: footer, children: _jsxs("div", { className: `${modalStyles.form} ${syncStatusStyles.syncStatusModal}`, children: [_jsxs("div", { className: syncStatusStyles.syncStatusTop, children: [_jsxs("div", { className: syncStatusStyles.syncStatusMetaHeader, children: [_jsx("div", { className: syncStatusStyles.syncStatusBadge, style: {
72
67
  borderColor: syncStatusMeta.border,
73
68
  background: syncStatusMeta.background,
74
69
  color: syncStatusMeta.color
75
- }, children: syncStatusMeta.label }), _jsxs("span", { className: syncStatusStyles.syncStatusLabel, children: ["Workspace: ", _jsx("code", { children: currentWorkspaceLabel })] })] }), _jsx("label", { className: syncStatusStyles.syncToggle, children: _jsxs("span", { className: [
76
- syncStatusStyles.syncToggleControl,
77
- workspaceCloudSyncEnabled ? syncStatusStyles.syncToggleControlEnabled : syncStatusStyles.syncToggleControlDisabled,
78
- syncControlBusy ? syncStatusStyles.syncToggleControlBusy : '',
79
- !canManageWorkspaceSync ? syncStatusStyles.syncToggleControlBlocked : ''
80
- ].filter(Boolean).join(' '), children: [_jsx("input", { className: syncStatusStyles.syncToggleInput, type: "checkbox", role: "switch", "aria-label": "Enable Sync", checked: workspaceCloudSyncEnabled, disabled: !canManageWorkspaceSync || syncControlBusy, onChange: (event) => onToggleWorkspaceSync(event.target.checked) }), _jsx("span", { className: `${syncStatusStyles.syncToggleState} ${syncStatusStyles.syncToggleStateOn}`, children: "On" }), _jsx("span", { className: `${syncStatusStyles.syncToggleState} ${syncStatusStyles.syncToggleStateOff}`, children: "Off" }), _jsx("span", { className: syncStatusStyles.syncToggleThumb })] }) })] }), _jsxs("section", { className: syncStatusStyles.syncStatusOverview, "aria-label": "Sync status", children: [_jsxs("div", { className: syncStatusStyles.syncStatusOverviewRow, children: [_jsx("span", { className: syncStatusStyles.syncStatusLabel, children: "Health" }), _jsx("span", { className: syncStatusStyles.syncStatusSummaryValue, children: workspaceSyncSummary })] }), _jsxs("div", { className: syncStatusStyles.syncStatusOverviewRow, children: [_jsx("span", { className: syncStatusStyles.syncStatusLabel, children: "Next step" }), _jsx("span", { className: syncStatusStyles.syncStatusSummaryValue, children: workspaceSyncRecommendedAction })] }), _jsxs("div", { className: [
70
+ }, children: syncStatusMeta.label }), _jsxs("span", { className: syncStatusStyles.syncStatusLabel, children: ["Workspace: ", _jsx("code", { children: currentWorkspaceLabel })] })] }), _jsxs("label", { className: syncStatusStyles.syncToggle, children: [syncControlTransitionLabel ? (_jsx("span", { className: syncStatusStyles.syncToggleTransition, "aria-live": "polite", children: syncControlTransitionLabel })) : null, _jsxs("span", { className: [
71
+ syncStatusStyles.syncToggleControl,
72
+ displayedSyncEnabled ? syncStatusStyles.syncToggleControlEnabled : syncStatusStyles.syncToggleControlDisabled,
73
+ syncControlBusy ? syncStatusStyles.syncToggleControlBusy : '',
74
+ !canManageWorkspaceSync ? syncStatusStyles.syncToggleControlBlocked : ''
75
+ ].filter(Boolean).join(' '), children: [_jsx("input", { className: syncStatusStyles.syncToggleInput, type: "checkbox", role: "switch", "aria-label": syncControlTransitionLabel || 'Enable Sync', checked: displayedSyncEnabled, disabled: !canManageWorkspaceSync || syncControlBusy, onChange: (event) => onToggleWorkspaceSync(event.target.checked) }), _jsx("span", { className: `${syncStatusStyles.syncToggleState} ${syncStatusStyles.syncToggleStateOn}`, children: "On" }), _jsx("span", { className: `${syncStatusStyles.syncToggleState} ${syncStatusStyles.syncToggleStateOff}`, children: "Off" }), _jsx("span", { className: syncStatusStyles.syncToggleThumb })] })] })] }), _jsxs("section", { className: syncStatusStyles.syncStatusOverview, "aria-label": "Sync status", children: [_jsxs("div", { className: syncStatusStyles.syncStatusOverviewRow, children: [_jsx("span", { className: syncStatusStyles.syncStatusLabel, children: "Health" }), _jsx("span", { className: syncStatusStyles.syncStatusSummaryValue, children: workspaceSyncSummary })] }), _jsxs("div", { className: syncStatusStyles.syncStatusOverviewRow, children: [_jsx("span", { className: syncStatusStyles.syncStatusLabel, children: "Next step" }), _jsx("span", { className: syncStatusStyles.syncStatusSummaryValue, children: workspaceSyncRecommendedAction })] }), _jsxs("div", { className: [
81
76
  syncStatusStyles.syncStatusOverviewRow,
82
77
  syncStatusStyles.syncStatusIssueRow,
83
78
  activeIssueIsError ? syncStatusStyles.syncStatusIssueRowError : '',
@@ -1,6 +1,7 @@
1
1
  import { resolveDeploymentConfig } from './deployment.js';
2
2
  import { MIGRATION_COMPAT_ENABLED } from '../runtime/migrationFlags.js';
3
3
  import { parseWorkspaceSyncV3FeedCursorKeyring } from '../sync/v3/workspaceSyncV3FeedCursorKeys.js';
4
+ import { resolveExecutorPhaseAApprovalSigningConfig } from '../services/executorPhaseAApprovalService.js';
4
5
  const SPECS = [
5
6
  { key: 'PORT', description: 'Standalone server port.', category: 'Core', defaultValue: '8080', targets: ['server', 'all'] },
6
7
  { key: 'TASKFORCE_TENANT_ID', description: 'Tenant identifier.', category: 'Core', defaultValue: 'default', targets: ['server', 'all'] },
@@ -66,7 +67,7 @@ const SPECS = [
66
67
  { key: 'TASKFORCE_SYNC_V3_LOCAL_FEED_APPLY_ENABLED', description: 'Enable the local-only atomic v3 initiative feed apply boundary.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
67
68
  { key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_ENABLED', description: 'Expose registered task-planning-metadata cloud feed and repair contracts.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
68
69
  { key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_ACTIVATION_ENABLED', description: 'Request combined coordinator activation; activation still requires exact local prerequisites and a matching ready cloud capability attestation.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
69
- { key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION', description: 'Request a frozen combined-feed coverage profile by registered version. Omit for version 3; version 4 adds nested task and entity-event coverage; version 5 adds workflow runtime coverage; version 6 extends version 4 with workstream task order.', category: 'Core', defaultValue: '3', targets: ['server', 'all'] },
70
+ { key: 'TASKFORCE_SYNC_V3_COMBINED_FEED_COVERAGE_VERSION', description: 'Request a frozen combined-feed coverage profile by registered version. Omit for version 3; version 4 adds nested task and entity-event coverage; version 5 adds workflow runtime coverage; version 6 adds workstream task order; version 7 adds explicit task card covers; version 8 composes workflow runtime with version 7.', category: 'Core', defaultValue: '3', targets: ['server', 'all'] },
70
71
  { key: 'TASKFORCE_SYNC_V3_COMBINED_LOCAL_FEED_APPLY_ENABLED', description: 'Enable local atomic apply for registered task-planning-metadata coverage profiles.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
71
72
  { key: 'TASKFORCE_SYNC_V3_COMBINED_LEGACY_FENCE_ENABLED', description: 'Configure the combined stale-v2 fence; it becomes effective only after every covered cloud HTTP and MCP writer boundary is ready.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
72
73
  { key: 'TASKFORCE_SYNC_V3_NESTED_LEGACY_FENCE_ENABLED', description: 'Fence the four v4-only legacy projections after every nested cloud writer boundary is ready.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
@@ -75,6 +76,7 @@ const SPECS = [
75
76
  { key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_DISPATCH_ENABLED', description: 'Enable local durable workflow runtime outbox dispatch when the shared dispatcher is enabled.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
76
77
  { key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_HTTP_ACTIVATION_ENABLED', description: 'Route workflow runtime HTTP commands through durable v3 acceptance or local capture.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
77
78
  { key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_MCP_ACTIVATION_ENABLED', description: 'Route workflow runtime MCP commands through durable v3 acceptance or local capture.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
79
+ { key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_MUTATIONS_FENCED', description: 'Temporarily reject workflow execution mutations during projection rollback.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
78
80
  { key: 'TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_CARRIER_COEXISTENCE_ENABLED', description: 'Acknowledge that task-status workflow activation remains the v5 bootstrap and rollback carrier.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
79
81
  { key: 'TASKFORCE_SYNC_V3_WORKSTREAM_TASK_ORDER_ENABLED', description: 'Enable cloud acceptance for durable v3 workstream task-order operations.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
80
82
  { key: 'TASKFORCE_SYNC_V3_WORKSTREAM_TASK_ORDER_CAPTURE_ENABLED', description: 'Enable local durable workstream task-order capture when the shared local capture and dispatch boundaries are enabled.', category: 'Core', defaultValue: 'false', targets: ['server', 'all'] },
@@ -89,6 +91,10 @@ const SPECS = [
89
91
  { key: 'TASKFORCE_AUTH_EXCLUDED_PATHS', description: 'Comma-separated API paths excluded from auth checks.', category: 'Auth', defaultValue: '/api/taskforce/health,/api/taskforce/version,/api/taskforce/auth,/api/taskforce/public/pricing,/api/taskforce/public/site-config,/api/taskforce/public/site-config-script', targets: ['server', 'all'] },
90
92
  { key: 'TASKFORCE_AUTH_DEFAULT_ROLE', description: 'Default role for unauthenticated context (owner|admin|member|read-only).', category: 'Auth', defaultValue: 'member', targets: ['server', 'all'] },
91
93
  { key: 'TASKFORCE_AUTH_SESSION_COOKIE', description: 'Session cookie name.', category: 'Auth', defaultValue: 'taskforce_session', targets: ['server', 'all'] },
94
+ { key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE', description: 'Upstream cloud session cookie name used by every admin proxy target unless overridden per environment.', category: 'Auth', defaultValue: 'taskforce_session', targets: ['server', 'all'] },
95
+ { key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE_PRODUCTION', description: 'Optional Production upstream session cookie name override for the admin proxy.', category: 'Auth', targets: ['server', 'all'] },
96
+ { key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE_STAGING', description: 'Optional Staging upstream session cookie name override for the admin proxy.', category: 'Auth', targets: ['server', 'all'] },
97
+ { key: 'TASKFORCE_ADMIN_PROXY_UPSTREAM_SESSION_COOKIE_PERFORMANCE', description: 'Optional Performance upstream session cookie name override for the admin proxy.', category: 'Auth', targets: ['server', 'all'] },
92
98
  { key: 'TASKFORCE_AUTH_SESSION_SECRET', description: 'Session signing secret.', category: 'Auth', secret: true, targets: ['server', 'all'] },
93
99
  { key: 'TASKFORCE_AUTH_SESSION_TTL_SECONDS', description: 'Session max age in seconds.', category: 'Auth', defaultValue: '2592000', targets: ['server', 'all'] },
94
100
  { key: 'TASKFORCE_AUTH_SESSION_SAMESITE', description: 'SameSite policy (Lax|Strict|None).', category: 'Auth', defaultValue: 'None', targets: ['server', 'all'] },
@@ -146,6 +152,7 @@ const SPECS = [
146
152
  { key: 'TASKFORCE_AGENT_SUBSCRIPTION_DEV_MODELS', description: 'Enable internal local-development-only Taskforce Agent subscription-auth model adapters such as OpenAI Codex app-server.', category: 'AI', defaultValue: 'false', targets: ['server', 'all'] },
147
153
  { key: 'TASKFORCE_CODEX_APP_SERVER_COMMAND', description: 'Optional Codex CLI command path for the internal OpenAI Codex app-server Taskforce Agent adapter.', category: 'AI', defaultValue: 'codex', targets: ['server', 'all'] },
148
154
  { key: 'TASKFORCE_CODEX_APP_SERVER_CWD', description: 'Optional working directory for the internal Codex app-server subprocess. Defaults to the system temp directory.', category: 'AI', targets: ['server', 'all'] },
155
+ { key: 'TASKFORCE_MODEL_CONNECTION_STORAGE_PATH', description: 'Restricted durable volume root for isolated user-owned model provider credential homes.', category: 'AI', targets: ['server', 'all'] },
149
156
  { key: 'TASKFORCE_ALLOWED_ORIGINS', description: 'Allowed CORS origins (comma-separated).', category: 'Security', targets: ['server', 'all'] },
150
157
  { key: 'TASKFORCE_API_RATE_LIMIT_ENABLED', description: 'Enable API rate limiter.', category: 'Security', defaultValue: 'true', targets: ['server', 'all'] },
151
158
  { key: 'TASKFORCE_API_RATE_LIMIT_MAX_REQUESTS', description: 'API rate limit max requests per window.', category: 'Security', defaultValue: '120', targets: ['server', 'all'] },
@@ -165,6 +172,12 @@ const SPECS = [
165
172
  { key: 'TASKFORCE_ADMIN_AUDIT_SYNC_RETENTION_DAYS', description: 'Retention period for non-routine sync audit failures and exceptional events.', category: 'Security', defaultValue: '30', targets: ['server', 'all'] },
166
173
  { key: 'TASKFORCE_ADMIN_AUDIT_RETENTION_DAYS', description: 'Default retention period for administrative and security audit events.', category: 'Security', defaultValue: '365', targets: ['server', 'all'] },
167
174
  { key: 'TASKFORCE_SYNC_KEY', description: 'Optional sync encryption key.', category: 'Security', secret: true, targets: ['server', 'all'] },
175
+ { key: 'TASKFORCE_GITHUB_REVIEW_APP_ID', description: 'GitHub App identifier used for private-repository review evidence.', category: 'Security', targets: ['server', 'all'] },
176
+ { key: 'TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64', description: 'Base64-encoded GitHub App private key used only to mint short-lived installation tokens.', category: 'Security', secret: true, targets: ['server', 'all'] },
177
+ { key: 'TASKFORCE_PHASE_A_APPROVAL_ISSUER_ENABLED', description: 'Enable performance-cloud Phase A approval receipt issuance.', category: 'Security', defaultValue: 'false', targets: ['server', 'all'] },
178
+ { key: 'TASKFORCE_PHASE_A_ISSUER_REDEMPTION_ENABLED', description: 'Expose the disabled performance-cloud Phase A issuer redemption boundary.', category: 'Security', defaultValue: 'false', targets: ['server', 'all'] },
179
+ { key: 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_KEY_ID', description: 'Active source-pinned Ed25519 key ID for performance Phase A approval receipts.', category: 'Security', targets: ['server', 'all'] },
180
+ { key: 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_PRIVATE_KEY_PKCS8_BASE64', description: 'Base64-encoded PKCS#8 Ed25519 private key for performance Phase A approval receipts.', category: 'Security', secret: true, targets: ['server', 'all'] },
168
181
  { key: 'TASKFORCE_STRIPE_SECRET_KEY', description: 'Stripe secret API key used by server-side billing routes.', category: 'Security', secret: true, targets: ['server', 'all'] },
169
182
  { key: 'TASKFORCE_STRIPE_WEBHOOK_SECRET', description: 'Stripe webhook signing secret used to verify incoming webhooks.', category: 'Security', secret: true, targets: ['server', 'all'] },
170
183
  { key: 'TASKFORCE_BUILD_VERSION', description: 'Build version metadata.', category: 'Build', targets: ['server', 'all'] },
@@ -206,6 +219,8 @@ const SPECS = [
206
219
  { key: 'SYNC_SOAK_OVERNIGHT_MAX_ACTIONS', description: 'Overnight hard cap on action count.', category: 'Soak', defaultValue: '10000', targets: ['soak', 'all'] },
207
220
  { key: 'SYNC_SOAK_OVERNIGHT_MIN_ACTIONS', description: 'Overnight minimum actions expected before pass.', category: 'Soak', defaultValue: '80', targets: ['soak', 'all'] },
208
221
  { key: 'SYNC_SOAK_OVERNIGHT_CLEAN_BASELINE_EVERY_ACTION', description: 'Require coordinator settlement before each accelerated overnight action.', category: 'Soak', defaultValue: 'false', targets: ['soak', 'all'] },
222
+ { key: 'SYNC_SOAK_SERVER_FAULT_PROFILE', description: 'Deterministic server-owned sync transport fault profile (none|operation-response-loss-once).', category: 'Soak', defaultValue: 'none', targets: ['soak', 'all'] },
223
+ { key: 'SYNC_SOAK_CLEAN_BASELINE_TIMEOUT_MS', description: 'Bounded wait for coordinator recovery and clean-baseline settlement.', category: 'Soak', defaultValue: '180000', targets: ['soak', 'all'] },
209
224
  { key: 'CF_ACCESS_CLIENT_ID', description: 'Cloudflare Access service token client id (soak).', category: 'Cloudflare', secret: true, targets: ['soak', 'all'] },
210
225
  { key: 'CF_ACCESS_CLIENT_SECRET', description: 'Cloudflare Access service token client secret (soak).', category: 'Cloudflare', secret: true, targets: ['soak', 'all'] }
211
226
  ];
@@ -357,6 +372,38 @@ function validateServerEnv(env, errors, warnings) {
357
372
  if (provider === 'postgres' && !hasValue(env, 'TASKFORCE_DATABASE_URL')) {
358
373
  errors.push('TASKFORCE_DATABASE_URL is required when TASKFORCE_DB_PROVIDER=postgres.');
359
374
  }
375
+ const hasGitHubReviewAppId = hasValue(env, 'TASKFORCE_GITHUB_REVIEW_APP_ID');
376
+ const hasGitHubReviewPrivateKey = hasValue(env, 'TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64');
377
+ if (hasGitHubReviewAppId !== hasGitHubReviewPrivateKey) {
378
+ errors.push('TASKFORCE_GITHUB_REVIEW_APP_ID and TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 must be configured together.');
379
+ }
380
+ if (hasGitHubReviewPrivateKey) {
381
+ const encoded = String(env.TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 || '').trim();
382
+ const decoded = Buffer.from(encoded, 'base64').toString('utf8');
383
+ if (!/^[A-Za-z0-9+/]+={0,2}$/.test(encoded) || !decoded.includes('-----BEGIN') || !decoded.includes('PRIVATE KEY-----')) {
384
+ errors.push('TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 must contain a base64-encoded PEM private key.');
385
+ }
386
+ }
387
+ const phaseAIssuerEnabled = parseBoolean(env.TASKFORCE_PHASE_A_APPROVAL_ISSUER_ENABLED) === true;
388
+ const phaseARedemptionEnabled = parseBoolean(env.TASKFORCE_PHASE_A_ISSUER_REDEMPTION_ENABLED) === true;
389
+ const hasPhaseAKeyId = hasValue(env, 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_KEY_ID');
390
+ const hasPhaseAPrivateKey = hasValue(env, 'TASKFORCE_PHASE_A_APPROVAL_SIGNING_PRIVATE_KEY_PKCS8_BASE64');
391
+ if (phaseAIssuerEnabled || hasPhaseAKeyId || hasPhaseAPrivateKey) {
392
+ if (runtimeMode !== 'cloud' || deployment.cloudEnvironment !== 'performance') {
393
+ errors.push('Phase A approval receipt signing is allowed only in the performance cloud runtime.');
394
+ }
395
+ }
396
+ if (phaseARedemptionEnabled && (runtimeMode !== 'cloud' || deployment.cloudEnvironment !== 'performance')) {
397
+ errors.push('Phase A issuer redemption is allowed only in the performance cloud runtime.');
398
+ }
399
+ if (hasValue(env, 'TASKFORCE_PHASE_A_APPROVAL_ISSUER_ENABLED') || hasPhaseAKeyId || hasPhaseAPrivateKey) {
400
+ try {
401
+ resolveExecutorPhaseAApprovalSigningConfig(env);
402
+ }
403
+ catch (error) {
404
+ errors.push(String(error?.message || error));
405
+ }
406
+ }
360
407
  if (billingEnabled && !hasValue(env, 'TASKFORCE_STRIPE_SECRET_KEY')) {
361
408
  errors.push('TASKFORCE_STRIPE_SECRET_KEY is required when TASKFORCE_BILLING_ENABLED=true.');
362
409
  }
@@ -1,5 +1,5 @@
1
1
  import type { DatabaseAdapter } from '../storage/databaseAdapter.js';
2
- import type { McpOAuthProvider, McpAccessTokenRecord, McpAccessTokenListResult, McpAccessTokenIssueResult, McpAccessTokenAuthResult, McpAccessTokenInspectionResult, McpOAuthClientRecord, McpOAuthConnectorGrantRecord, McpOAuthTokenExchangeResult, McpOAuthAccessTokenAuthResult } from './types.js';
2
+ import type { McpCloudToolProfile, McpOAuthProvider, McpAccessTokenRecord, McpAccessTokenListResult, McpAccessTokenIssueResult, McpAccessTokenAuthResult, McpAccessTokenInspectionResult, McpOAuthClientRecord, McpOAuthConnectorGrantRecord, McpOAuthTokenExchangeResult, McpOAuthAccessTokenAuthResult } from './types.js';
3
3
  export interface McpTokenServiceDeps {
4
4
  /** Resolve plan/account access state for a given user */
5
5
  getAccountAccessStatus: (userId: string) => {
@@ -19,6 +19,8 @@ export declare class McpTokenService {
19
19
  private normalizeAccessRole;
20
20
  private normalizePermissionMode;
21
21
  private normalizeMcpAccessTokenScopes;
22
+ private normalizeMcpCloudToolProfile;
23
+ private requireMcpCloudToolProfile;
22
24
  private createMcpAccessTokenPrefix;
23
25
  private parseMcpAccessToken;
24
26
  private normalizeMcpOAuthProvider;
@@ -38,6 +40,7 @@ export declare class McpTokenService {
38
40
  private resolveMcpAccessTokenStatus;
39
41
  private rowToMcpAccessTokenRecord;
40
42
  private assertCanManageOwnMcpAccessToken;
43
+ private requireMcpToolProfileAdministrator;
41
44
  private countActiveMcpAccessTokens;
42
45
  revokeMcpCredentialsForUserWorkspace(userId: string, workspaceId: string, revokedByUserId?: string | null): void;
43
46
  revokeMcpCredentialsForWorkspace(workspaceId: string, revokedByUserId?: string | null): void;
@@ -52,6 +55,7 @@ export declare class McpTokenService {
52
55
  workspaceId: string;
53
56
  name: string;
54
57
  scopes: unknown;
58
+ toolProfile?: McpCloudToolProfile;
55
59
  expiresAt?: string | null;
56
60
  createdByIp?: string | null;
57
61
  }): McpAccessTokenIssueResult;
@@ -71,6 +75,15 @@ export declare class McpTokenService {
71
75
  tokenId: string;
72
76
  createdByIp?: string | null;
73
77
  }): McpAccessTokenIssueResult;
78
+ updateMcpAccessTokenToolProfile(input: {
79
+ actorUserId: string;
80
+ workspaceId: string;
81
+ tokenId: string;
82
+ toolProfile: unknown;
83
+ }): {
84
+ record: McpAccessTokenRecord;
85
+ previousToolProfile: McpCloudToolProfile;
86
+ };
74
87
  authenticateMcpAccessToken(token: string, workspaceId?: string): McpAccessTokenAuthResult | null;
75
88
  inspectMcpAccessToken(token: string): McpAccessTokenInspectionResult | null;
76
89
  recordMcpAccessTokenUsage(input: {
@@ -116,6 +129,15 @@ export declare class McpTokenService {
116
129
  workspaceId: string;
117
130
  grantId: string;
118
131
  }): McpOAuthConnectorGrantRecord;
132
+ updateMcpOAuthConnectorGrantToolProfile(input: {
133
+ actorUserId: string;
134
+ workspaceId: string;
135
+ grantId: string;
136
+ toolProfile: unknown;
137
+ }): {
138
+ record: McpOAuthConnectorGrantRecord;
139
+ previousToolProfile: McpCloudToolProfile;
140
+ };
119
141
  authenticateMcpOAuthAccessToken(token: string, workspaceId?: string): McpOAuthAccessTokenAuthResult | null;
120
142
  bindMcpOAuthConnectorGrantAiProfile(input: {
121
143
  grantId: string;
@@ -7,6 +7,7 @@ const MCP_ACCESS_TOKEN_DEFAULT_PAGE_SIZE = 20;
7
7
  const MCP_ACCESS_TOKEN_MAX_PAGE_SIZE = 100;
8
8
  const MCP_ACCESS_TOKEN_ALLOWED_SCOPES = ['tasks:read', 'tasks:write', 'workspace:read'];
9
9
  const MCP_OAUTH_AUTH_CODE_TTL_MS = 10 * 60 * 1000;
10
+ const MCP_CLOUD_TOOL_PROFILES = ['default', 'extended'];
10
11
  /**
11
12
  * Handles MCP direct-access tokens and MCP OAuth connector flow
12
13
  * (client registration, authorization codes, token exchange, grant lifecycle).
@@ -52,6 +53,19 @@ export class McpTokenService {
52
53
  }
53
54
  return unique;
54
55
  }
56
+ normalizeMcpCloudToolProfile(value, fallback = 'default') {
57
+ const normalized = String(value || '').trim().toLowerCase();
58
+ return MCP_CLOUD_TOOL_PROFILES.includes(normalized)
59
+ ? normalized
60
+ : fallback;
61
+ }
62
+ requireMcpCloudToolProfile(value) {
63
+ const normalized = String(value || '').trim().toLowerCase();
64
+ if (!MCP_CLOUD_TOOL_PROFILES.includes(normalized)) {
65
+ throw new TaskforceRuleError('toolProfile must be default or extended', 400, 'MCP_TOOL_PROFILE_INVALID');
66
+ }
67
+ return normalized;
68
+ }
55
69
  createMcpAccessTokenPrefix() {
56
70
  return `tfmcp_${randomBytes(6).toString('hex')}`;
57
71
  }
@@ -204,6 +218,7 @@ export class McpTokenService {
204
218
  workspaceId: String(row?.workspace_id || ''),
205
219
  userId: String(row?.user_id || ''),
206
220
  scopes,
221
+ toolProfile: this.normalizeMcpCloudToolProfile(row?.tool_profile),
207
222
  tokenPrefix: String(row?.token_prefix || ''),
208
223
  status: this.resolveMcpOAuthGrantStatus(row),
209
224
  lastUsedAt: row?.last_used_at ? String(row.last_used_at) : null,
@@ -286,6 +301,7 @@ export class McpTokenService {
286
301
  u.email AS user_email,
287
302
  t.name,
288
303
  t.scopes_json,
304
+ t.tool_profile,
289
305
  t.token_prefix,
290
306
  t.token_hash,
291
307
  t.status,
@@ -331,6 +347,7 @@ export class McpTokenService {
331
347
  userEmail: row.user_email ? String(row.user_email) : null,
332
348
  name: String(row.name || ''),
333
349
  scopes,
350
+ toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
334
351
  tokenPrefix: String(row.token_prefix || ''),
335
352
  status: this.resolveMcpAccessTokenStatus(row),
336
353
  lastUsedAt: row.last_used_at ? String(row.last_used_at) : null,
@@ -353,6 +370,12 @@ export class McpTokenService {
353
370
  throw new TaskforceRuleError('Forbidden', 403, 'FORBIDDEN');
354
371
  }
355
372
  }
373
+ requireMcpToolProfileAdministrator(actorUserId, workspaceId) {
374
+ const member = this.getActiveWorkspaceMemberForMcp(actorUserId, workspaceId);
375
+ if (member.role !== 'owner' && member.role !== 'admin') {
376
+ throw new TaskforceRuleError('Workspace owner or admin access is required', 403, 'MCP_TOOL_PROFILE_ADMIN_REQUIRED');
377
+ }
378
+ }
356
379
  countActiveMcpAccessTokens(userId, workspaceId) {
357
380
  const now = new Date().toISOString();
358
381
  const row = this.db.prepare(`
@@ -446,6 +469,7 @@ export class McpTokenService {
446
469
  u.email AS user_email,
447
470
  t.name,
448
471
  t.scopes_json,
472
+ t.tool_profile,
449
473
  t.token_prefix,
450
474
  t.token_hash,
451
475
  t.status,
@@ -480,6 +504,7 @@ export class McpTokenService {
480
504
  throw new TaskforceRuleError('Token name is required', 400, 'MCP_TOKEN_NAME_REQUIRED');
481
505
  }
482
506
  const scopes = this.normalizeMcpAccessTokenScopes(input.scopes);
507
+ const toolProfile = this.normalizeMcpCloudToolProfile(input.toolProfile);
483
508
  const expiresAt = input.expiresAt ? String(input.expiresAt).trim() : null;
484
509
  const now = new Date().toISOString();
485
510
  if (expiresAt && expiresAt <= now) {
@@ -501,12 +526,12 @@ export class McpTokenService {
501
526
  const createdByIp = input.createdByIp ? String(input.createdByIp).trim() : null;
502
527
  this.db.prepare(`
503
528
  INSERT INTO mcp_access_tokens (
504
- id, tenant_id, workspace_id, user_id, name, scopes_json, token_prefix, token_hash, status,
529
+ id, tenant_id, workspace_id, user_id, name, scopes_json, tool_profile, token_prefix, token_hash, status,
505
530
  last_used_at, last_used_ip, last_used_user_agent, created_by_ip, expires_at, revoked_at,
506
531
  revoked_by_user_id, created_at, updated_at
507
532
  )
508
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, NULL, NULL, ?, ?)
509
- `).run(tokenId, this.tenantId, member.workspaceId, member.userId, name, JSON.stringify(scopes), tokenPrefix, tokenHash, createdByIp, expiresAt, now, now);
533
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, NULL, NULL, ?, ?)
534
+ `).run(tokenId, this.tenantId, member.workspaceId, member.userId, name, JSON.stringify(scopes), toolProfile, tokenPrefix, tokenHash, createdByIp, expiresAt, now, now);
510
535
  const row = this.getMcpAccessTokenRow(tokenId, member.workspaceId);
511
536
  if (!row) {
512
537
  throw new TaskforceRuleError('Failed to create MCP token', 500, 'MCP_TOKEN_CREATE_FAILED');
@@ -573,18 +598,39 @@ export class McpTokenService {
573
598
  workspaceId: revoked.workspaceId,
574
599
  name: revoked.name,
575
600
  scopes: revoked.scopes,
601
+ toolProfile: revoked.toolProfile,
576
602
  expiresAt: revoked.expiresAt || null,
577
603
  createdByIp: input.createdByIp || null,
578
604
  });
579
605
  });
580
606
  return tx();
581
607
  }
608
+ updateMcpAccessTokenToolProfile(input) {
609
+ this.requireMcpToolProfileAdministrator(input.actorUserId, input.workspaceId);
610
+ const row = this.getMcpAccessTokenRow(input.tokenId, input.workspaceId);
611
+ if (!row) {
612
+ throw new TaskforceRuleError('MCP token not found', 404, 'MCP_TOKEN_NOT_FOUND');
613
+ }
614
+ const previousToolProfile = this.normalizeMcpCloudToolProfile(row.tool_profile);
615
+ const toolProfile = this.requireMcpCloudToolProfile(input.toolProfile);
616
+ const now = new Date().toISOString();
617
+ this.db.prepare(`
618
+ UPDATE mcp_access_tokens
619
+ SET tool_profile = ?, updated_at = ?
620
+ WHERE tenant_id = ? AND workspace_id = ? AND id = ?
621
+ `).run(toolProfile, now, this.tenantId, input.workspaceId, row.id);
622
+ const updated = this.getMcpAccessTokenRow(row.id, input.workspaceId);
623
+ if (!updated) {
624
+ throw new TaskforceRuleError('MCP token not found', 404, 'MCP_TOKEN_NOT_FOUND');
625
+ }
626
+ return { record: this.rowToMcpAccessTokenRecord(updated), previousToolProfile };
627
+ }
582
628
  authenticateMcpAccessToken(token, workspaceId) {
583
629
  const parsed = this.parseMcpAccessToken(token);
584
630
  if (!parsed)
585
631
  return null;
586
632
  const row = this.db.prepare(`
587
- SELECT id, workspace_id, user_id, scopes_json, token_hash, status, expires_at, revoked_at
633
+ SELECT id, workspace_id, user_id, scopes_json, tool_profile, token_hash, status, expires_at, revoked_at
588
634
  FROM mcp_access_tokens
589
635
  WHERE tenant_id = ?
590
636
  AND token_prefix = ?
@@ -612,6 +658,7 @@ export class McpTokenService {
612
658
  workspaceId: row.workspace_id,
613
659
  userId: row.user_id,
614
660
  scopes,
661
+ toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
615
662
  status,
616
663
  };
617
664
  }
@@ -620,7 +667,7 @@ export class McpTokenService {
620
667
  if (!parsed)
621
668
  return null;
622
669
  const row = this.db.prepare(`
623
- SELECT id, workspace_id, user_id, name, scopes_json, token_hash, status, expires_at, revoked_at
670
+ SELECT id, workspace_id, user_id, name, scopes_json, tool_profile, token_hash, status, expires_at, revoked_at
624
671
  FROM mcp_access_tokens
625
672
  WHERE tenant_id = ?
626
673
  AND token_prefix = ?
@@ -644,6 +691,7 @@ export class McpTokenService {
644
691
  userId: row.user_id,
645
692
  name: String(row.name || ''),
646
693
  scopes,
694
+ toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
647
695
  status: this.resolveMcpAccessTokenStatus(row),
648
696
  };
649
697
  }
@@ -783,7 +831,7 @@ export class McpTokenService {
783
831
  const clientName = String(client.client_name || this.defaultMcpOAuthClientName(provider)).trim() || this.defaultMcpOAuthClientName(provider);
784
832
  const tx = this.db.transaction(() => {
785
833
  const existingRows = this.db.prepare(`
786
- SELECT id, ai_profile_id, ai_profile_token, ai_profile_name
834
+ SELECT id, tool_profile, ai_profile_id, ai_profile_token, ai_profile_name
787
835
  FROM mcp_oauth_connector_grants
788
836
  WHERE tenant_id = ?
789
837
  AND provider = ?
@@ -794,6 +842,7 @@ export class McpTokenService {
794
842
  ORDER BY created_at DESC
795
843
  `).all(this.tenantId, provider, String(client.id), String(row.user_id), String(row.workspace_id));
796
844
  const previousBinding = existingRows.find((existing) => existing.ai_profile_id && existing.ai_profile_token && existing.ai_profile_name) || null;
845
+ const toolProfile = this.normalizeMcpCloudToolProfile(existingRows[0]?.tool_profile);
797
846
  const revokeTime = new Date().toISOString();
798
847
  existingRows.forEach((existing) => {
799
848
  if (!existing?.id)
@@ -819,12 +868,12 @@ export class McpTokenService {
819
868
  const tokenHash = hashMcpOAuthSecret(secret);
820
869
  this.db.prepare(`
821
870
  INSERT INTO mcp_oauth_connector_grants (
822
- id, tenant_id, provider, client_id, client_name, product_client_id, user_id, workspace_id, scopes_json,
871
+ id, tenant_id, provider, client_id, client_name, product_client_id, user_id, workspace_id, scopes_json, tool_profile,
823
872
  token_prefix, token_hash, status, last_used_at, revoked_at, revoked_by_user_id,
824
873
  ai_profile_id, ai_profile_token, ai_profile_name, created_at, updated_at
825
874
  )
826
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, ?, ?, ?)
827
- `).run(grantId, this.tenantId, provider, String(client.id || ''), clientName, client.product_client_id ? String(client.product_client_id) : null, String(row.user_id), String(row.workspace_id), JSON.stringify(scopes), tokenPrefix, tokenHash, previousBinding?.ai_profile_id || null, previousBinding?.ai_profile_token || null, previousBinding?.ai_profile_name || null, now, now);
875
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, ?, ?, ?)
876
+ `).run(grantId, this.tenantId, provider, String(client.id || ''), clientName, client.product_client_id ? String(client.product_client_id) : null, String(row.user_id), String(row.workspace_id), JSON.stringify(scopes), toolProfile, tokenPrefix, tokenHash, previousBinding?.ai_profile_id || null, previousBinding?.ai_profile_token || null, previousBinding?.ai_profile_name || null, now, now);
828
877
  this.db.prepare(`
829
878
  UPDATE mcp_oauth_auth_codes
830
879
  SET used_at = ?
@@ -909,12 +958,45 @@ export class McpTokenService {
909
958
  }
910
959
  return this.rowToMcpOAuthConnectorGrantRecord(updated);
911
960
  }
961
+ updateMcpOAuthConnectorGrantToolProfile(input) {
962
+ this.requireMcpToolProfileAdministrator(input.actorUserId, input.workspaceId);
963
+ const row = this.db.prepare(`
964
+ SELECT *
965
+ FROM mcp_oauth_connector_grants
966
+ WHERE tenant_id = ? AND workspace_id = ? AND id = ?
967
+ LIMIT 1
968
+ `).get(this.tenantId, input.workspaceId, String(input.grantId || '').trim());
969
+ if (!row?.id) {
970
+ throw new TaskforceRuleError('MCP connector grant not found', 404, 'MCP_OAUTH_GRANT_NOT_FOUND');
971
+ }
972
+ const previousToolProfile = this.normalizeMcpCloudToolProfile(row.tool_profile);
973
+ const toolProfile = this.requireMcpCloudToolProfile(input.toolProfile);
974
+ const now = new Date().toISOString();
975
+ this.db.prepare(`
976
+ UPDATE mcp_oauth_connector_grants
977
+ SET tool_profile = ?, updated_at = ?
978
+ WHERE tenant_id = ? AND workspace_id = ? AND id = ?
979
+ `).run(toolProfile, now, this.tenantId, input.workspaceId, String(row.id));
980
+ const updated = this.db.prepare(`
981
+ SELECT *
982
+ FROM mcp_oauth_connector_grants
983
+ WHERE tenant_id = ? AND workspace_id = ? AND id = ?
984
+ LIMIT 1
985
+ `).get(this.tenantId, input.workspaceId, String(row.id));
986
+ if (!updated) {
987
+ throw new TaskforceRuleError('MCP connector grant not found', 404, 'MCP_OAUTH_GRANT_NOT_FOUND');
988
+ }
989
+ return {
990
+ record: this.rowToMcpOAuthConnectorGrantRecord(updated),
991
+ previousToolProfile,
992
+ };
993
+ }
912
994
  authenticateMcpOAuthAccessToken(token, workspaceId) {
913
995
  const parsed = this.parseMcpOAuthOpaqueSecret(token, 'tfmcpoauth_');
914
996
  if (!parsed)
915
997
  return null;
916
998
  const row = this.db.prepare(`
917
- SELECT id, provider, client_id, product_client_id, user_id, workspace_id, scopes_json, token_hash, status, revoked_at,
999
+ SELECT id, provider, client_id, product_client_id, user_id, workspace_id, scopes_json, tool_profile, token_hash, status, revoked_at,
918
1000
  ai_profile_id, ai_profile_token, ai_profile_name
919
1001
  FROM mcp_oauth_connector_grants
920
1002
  WHERE tenant_id = ?
@@ -945,6 +1027,7 @@ export class McpTokenService {
945
1027
  provider: this.normalizeMcpOAuthProvider(row.provider),
946
1028
  productClientId: row?.product_client_id ? String(row.product_client_id) : null,
947
1029
  scopes,
1030
+ toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
948
1031
  status: this.resolveMcpOAuthGrantStatus(row),
949
1032
  aiProfileId: row?.ai_profile_id ? String(row.ai_profile_id) : null,
950
1033
  aiProfileToken: row?.ai_profile_token ? String(row.ai_profile_token) : null,
@@ -9,11 +9,23 @@ export interface TaskChecklistItem {
9
9
  }
10
10
  export interface TaskChecklistTask {
11
11
  id: string;
12
+ checklistItems?: TaskChecklistItem[];
12
13
  }
13
14
  export interface TaskChecklistReplaceMutation {
14
15
  taskId: string;
15
16
  items: TaskChecklistItem[];
16
17
  operationId: string;
18
+ expectedDetailRevision?: string;
19
+ requireDurableIdempotency?: boolean;
20
+ itemUpdateIntent?: {
21
+ kind: 'item-update';
22
+ itemId: string;
23
+ patch: {
24
+ text?: string;
25
+ done?: boolean;
26
+ order?: number;
27
+ };
28
+ };
17
29
  }
18
30
  export interface TaskChecklistCommandServiceDependencies {
19
31
  resolveTask(identifier: unknown): TaskChecklistTask;
@@ -35,6 +47,9 @@ export type ReplaceTaskChecklistCommandResult = {
35
47
  export type AddTaskChecklistItemCommandResult = ReplaceTaskChecklistCommandResult & {
36
48
  item: TaskChecklistItem | null;
37
49
  };
50
+ export type UpdateTaskChecklistItemCommandResult = ReplaceTaskChecklistCommandResult & {
51
+ item: TaskChecklistItem;
52
+ };
38
53
  export declare function createTaskChecklistCommandService(deps: TaskChecklistCommandServiceDependencies): {
39
54
  replace(input: {
40
55
  taskId: unknown;
@@ -47,4 +62,16 @@ export declare function createTaskChecklistCommandService(deps: TaskChecklistCom
47
62
  isCompleted?: unknown;
48
63
  done?: unknown;
49
64
  }): AddTaskChecklistItemCommandResult;
65
+ update(input: {
66
+ taskId: unknown;
67
+ itemId: unknown;
68
+ title?: unknown;
69
+ text?: unknown;
70
+ isCompleted?: unknown;
71
+ done?: unknown;
72
+ order?: unknown;
73
+ expectedDetailRevision?: unknown;
74
+ operationId?: string;
75
+ requireDurableIdempotency?: boolean;
76
+ }): UpdateTaskChecklistItemCommandResult;
50
77
  };