@taskforcehq/taskforce 0.3.327 → 0.3.329

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/dist/Taskforce.module.css +257 -87
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/activity/EntityActivityTimeline.js +15 -5
  8. package/dist/components/context/AttachmentPreviewHost.js +1 -1
  9. package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
  10. package/dist/components/context/ContextAttachmentManager.js +116 -20
  11. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  12. package/dist/components/features/TaskSettings.d.ts +12 -1
  13. package/dist/components/features/TaskSettings.js +147 -40
  14. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  15. package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
  16. package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
  17. package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
  18. package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
  19. package/dist/components/features/planning/PlanningModule.js +28 -14
  20. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  21. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  22. package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
  23. package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
  24. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  25. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  26. package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
  27. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  28. package/dist/components/task/TaskActionHeader.d.ts +2 -1
  29. package/dist/components/task/TaskActionHeader.js +2 -2
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +101 -13
  32. package/dist/components/task/TaskContextUpload.d.ts +3 -0
  33. package/dist/components/task/TaskContextUpload.js +2 -2
  34. package/dist/components/task/TaskForm.d.ts +4 -0
  35. package/dist/components/task/TaskForm.js +32 -7
  36. package/dist/components/task/TaskImageReviews.js +28 -19
  37. package/dist/components/task/TaskKanban.d.ts +6 -1
  38. package/dist/components/task/TaskKanban.js +152 -6
  39. package/dist/components/task/TaskList.d.ts +5 -0
  40. package/dist/components/task/TaskList.js +3 -3
  41. package/dist/components/task/TaskStatusActions.js +11 -2
  42. package/dist/components/task/TaskWorkstreamPicker.js +2 -1
  43. package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
  44. package/dist/components/ui/DocumentTypeIcon.js +8 -0
  45. package/dist/components/ui/PasswordInput.d.ts +6 -0
  46. package/dist/components/ui/PasswordInput.js +11 -0
  47. package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
  48. package/dist/components/ui/TaxonomyDropdown.js +30 -3
  49. package/dist/components/ui/TopNoticeLayer.js +1 -1
  50. package/dist/components/views/AppShellHeader.js +32 -11
  51. package/dist/components/views/PlanComparisonPage.js +12 -0
  52. package/dist/components/views/StandaloneLayout.js +68 -39
  53. package/dist/components/views/WidgetView.js +10 -7
  54. package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
  55. package/dist/components/views/panels/PlanningDrawer.js +51 -54
  56. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  57. package/dist/config/envSchema.js +13 -0
  58. package/dist/config/localServiceCloudTarget.d.ts +10 -0
  59. package/dist/config/localServiceCloudTarget.js +76 -0
  60. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  61. package/dist/config/localServiceRuntimeContract.js +135 -0
  62. package/dist/core/AiProfileService.d.ts +1 -0
  63. package/dist/core/AiProfileService.js +48 -9
  64. package/dist/core/AttachmentLinkService.js +7 -4
  65. package/dist/core/DeletedTaskLifecycleService.d.ts +5 -0
  66. package/dist/core/DeletedTaskLifecycleService.js +55 -3
  67. package/dist/core/McpTokenService.d.ts +4 -0
  68. package/dist/core/McpTokenService.js +52 -0
  69. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +8 -2
  70. package/dist/core/TaskAttachmentLinksDurableMutationService.js +51 -18
  71. package/dist/core/Taskforce.d.ts +124 -2
  72. package/dist/core/Taskforce.js +1175 -87
  73. package/dist/core/types.d.ts +8 -1
  74. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
  75. package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
  76. package/dist/documentReviews/service.d.ts +4 -0
  77. package/dist/documentReviews/service.js +141 -46
  78. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  79. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  80. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  81. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  82. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  83. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  84. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  85. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  86. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  87. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  88. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  89. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  90. package/dist/hooks/tasks/useTaskFormActions.d.ts +9 -0
  91. package/dist/hooks/tasks/useTaskFormActions.js +96 -17
  92. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  93. package/dist/hooks/ui/useSettingsModel.js +13 -2
  94. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  95. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  96. package/dist/hooks/useFilterSort.d.ts +7 -3
  97. package/dist/hooks/useFilterSort.js +15 -5
  98. package/dist/hooks/useTaskData.d.ts +10 -1
  99. package/dist/hooks/useTaskData.js +216 -7
  100. package/dist/hooks/useTaskMutations.d.ts +10 -2
  101. package/dist/hooks/useTaskMutations.js +223 -43
  102. package/dist/hooks/useTaskforce.d.ts +94 -57
  103. package/dist/hooks/useTaskforce.js +428 -16
  104. package/dist/hooks/useUiNotice.d.ts +4 -0
  105. package/dist/hooks/useUiNotice.js +4 -0
  106. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  107. package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
  108. package/dist/mcp/canonicalAssetHelpers.js +39 -5
  109. package/dist/mcp/collaborationRegistrar.js +15 -13
  110. package/dist/mcp/documentAssetRegistrar.js +60 -44
  111. package/dist/mcp/documentHelpers.d.ts +1 -0
  112. package/dist/mcp/documentHelpers.js +7 -3
  113. package/dist/mcp/localServiceProxy.js +4 -1
  114. package/dist/mcp/runtime.d.ts +16 -0
  115. package/dist/mcp/runtime.js +735 -210
  116. package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
  117. package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
  118. package/dist/mcp/taskPlanningRegistrar.js +78 -67
  119. package/dist/mcp/toolCallCompatibility.js +38 -1
  120. package/dist/mcp/toolCatalog.d.ts +1 -0
  121. package/dist/mcp/toolRegistry.js +2 -2
  122. package/dist/migrations/taskSchemaMigrations.js +47 -0
  123. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  124. package/dist/runtime/appGateDefinitions.js +6 -6
  125. package/dist/runtime/appGates.d.ts +12 -13
  126. package/dist/runtime/appGates.js +29 -13
  127. package/dist/runtime/nodeAppGates.d.ts +8 -0
  128. package/dist/runtime/nodeAppGates.js +27 -0
  129. package/dist/server/appAccess.d.ts +12 -0
  130. package/dist/server/appAccess.js +21 -0
  131. package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
  132. package/dist/server/authorizedWorkspaceAccess.js +40 -0
  133. package/dist/server/cloudCollectionRead.d.ts +25 -0
  134. package/dist/server/cloudCollectionRead.js +120 -0
  135. package/dist/server/cloudCollectionReadPool.d.ts +52 -0
  136. package/dist/server/cloudCollectionReadPool.js +140 -0
  137. package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
  138. package/dist/server/cloudCollectionReadWorker.js +36 -0
  139. package/dist/server/index.d.ts +6 -11
  140. package/dist/server/index.js +67 -42
  141. package/dist/server/localServiceLease.d.ts +6 -0
  142. package/dist/server/localServiceLease.js +17 -1
  143. package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
  144. package/dist/server/rateLimit.d.ts +1 -0
  145. package/dist/server/rateLimit.js +4 -0
  146. package/dist/server/realtimeSyncWs.js +36 -12
  147. package/dist/server/routes/admin.js +1 -0
  148. package/dist/server/routes/agentRoles.js +3 -2
  149. package/dist/server/routes/agentSkills.js +3 -2
  150. package/dist/server/routes/agents.js +118 -16
  151. package/dist/server/routes/annotatedAttachments.js +3 -2
  152. package/dist/server/routes/auth.js +3 -1
  153. package/dist/server/routes/documents.d.ts +5 -2
  154. package/dist/server/routes/documents.js +160 -13
  155. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  156. package/dist/server/routes/durableTaskHttpRouters.js +2 -2
  157. package/dist/server/routes/localService.js +4 -0
  158. package/dist/server/routes/primitives.d.ts +4 -0
  159. package/dist/server/routes/shared.d.ts +24 -0
  160. package/dist/server/routes/shared.js +114 -18
  161. package/dist/server/routes/sync.js +22 -0
  162. package/dist/server/routes/syncAuxRoutes.js +5 -2
  163. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  164. package/dist/server/routes/syncV3FeedRoutes.js +22 -18
  165. package/dist/server/routes/syncV3LocalCaptureRoutes.js +48 -4
  166. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  167. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  168. package/dist/server/routes/syncV3OperationRoutes.js +27 -2
  169. package/dist/server/routes/tasks.js +299 -97
  170. package/dist/server/routes/workspaces.js +43 -1
  171. package/dist/server/routes.js +35 -7
  172. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  173. package/dist/server/workspaceDeletionAdmission.js +50 -0
  174. package/dist/service/localServiceCli.js +52 -25
  175. package/dist/service/localServiceClientLifecycle.js +93 -6
  176. package/dist/services/codexAppServerModelGateway.d.ts +112 -0
  177. package/dist/services/codexAppServerModelGateway.js +438 -0
  178. package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
  179. package/dist/services/taskforceAgentMcpBridge.js +23 -3
  180. package/dist/shared/planningIdentity.d.ts +20 -0
  181. package/dist/shared/planningIdentity.js +79 -0
  182. package/dist/shared/taskforceAgentDefinition.js +7 -1
  183. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  184. package/dist/shared/taskforceAgentModels.js +30 -1
  185. package/dist/storage/postgresAdapter.d.ts +20 -3
  186. package/dist/storage/postgresAdapter.js +110 -14
  187. package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
  188. package/dist/storage/postgresRequestDiagnostics.js +24 -0
  189. package/dist/storage/postgresWorker.js +13 -4
  190. package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
  191. package/dist/storage/postgresWorkerProtocol.js +30 -0
  192. package/dist/storage/workspaceAssetStore.d.ts +32 -0
  193. package/dist/storage/workspaceAssetStore.js +70 -0
  194. package/dist/sync/cloudSyncApi.d.ts +4 -1
  195. package/dist/sync/cloudSyncApi.js +7 -2
  196. package/dist/sync/contentSyncState.d.ts +1 -1
  197. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +17 -0
  198. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +77 -23
  199. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  200. package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
  201. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  202. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  203. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  204. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +16 -0
  205. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  206. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
  207. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +46 -4
  208. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  209. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +51 -11
  210. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  211. package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
  212. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
  213. package/dist/sync/syncApplyHandlers.d.ts +3 -1
  214. package/dist/sync/syncApplyHandlers.js +29 -0
  215. package/dist/sync/syncService.d.ts +2 -0
  216. package/dist/sync/syncService.js +13 -1
  217. package/dist/sync/taskSyncPayload.d.ts +1 -0
  218. package/dist/sync/taskSyncPayload.js +6 -0
  219. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  220. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +3 -0
  221. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +31 -3
  222. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
  223. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
  224. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  225. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +47 -12
  226. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  227. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
  228. package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
  229. package/dist/sync/v3/localOutboxDispatcher.js +5 -1
  230. package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
  231. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +3 -0
  232. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +62 -10
  233. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  234. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  235. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  236. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  237. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  238. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  239. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  240. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  241. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  242. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
  243. package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
  244. package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
  245. package/dist/sync/v3/syncDurabilityStore.d.ts +15 -0
  246. package/dist/sync/v3/syncDurabilityStore.js +201 -43
  247. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +7 -4
  248. package/dist/sync/v3/taskAttachmentLinksMutationService.js +37 -12
  249. package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
  250. package/dist/sync/v3/taskChecklistMutationService.js +4 -0
  251. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  252. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  253. package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
  254. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  255. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  256. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  257. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  258. package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
  259. package/dist/sync/v3/taskStatusMutationService.js +4 -0
  260. package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
  261. package/dist/sync/v3/workflowAssignmentSync.js +3 -0
  262. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  263. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +14 -12
  264. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  265. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  266. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  267. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  268. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +10 -1
  269. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +15 -4
  270. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +66 -13
  271. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +11 -0
  272. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +57 -22
  273. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +10 -4
  274. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -51
  275. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  276. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +120 -28
  277. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
  278. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
  279. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  280. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  281. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  282. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  283. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  284. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  285. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  286. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  287. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  288. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  289. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  290. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  291. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  292. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
  293. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
  294. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
  295. package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
  296. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  297. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  298. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  299. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  300. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  301. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
  302. package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
  303. package/dist/sync/workspacePullFeed.d.ts +6 -1
  304. package/dist/sync/workspacePullFeed.js +174 -162
  305. package/dist/sync/workspaceRepair.d.ts +3 -0
  306. package/dist/sync/workspaceRepair.js +67 -6
  307. package/dist/sync/workspaceSyncModel.d.ts +11 -0
  308. package/dist/sync/workspaceSyncModel.js +27 -2
  309. package/dist/types.d.ts +55 -1
  310. package/dist/types.js +6 -0
  311. package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
  312. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
  313. package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
  314. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  315. package/dist/ui/assets/AssetTraySortControl-C8Rztyal.js +1 -0
  316. package/dist/ui/assets/ContextAttachmentManager-Cj3c7X9y.js +3 -0
  317. package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-B5uvzems.js} +4 -4
  318. package/dist/ui/assets/EntityActivityTimeline-BVFvCB5R.js +1 -0
  319. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
  320. package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
  321. package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
  322. package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
  323. package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
  324. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
  325. package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
  326. package/dist/ui/assets/WorkflowManagerModule-DEr5di_r.js +1 -0
  327. package/dist/ui/assets/index-I5zhdtgt.js +7 -0
  328. package/dist/ui/assets/index-VRFsx3wz.css +1 -0
  329. package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-D9Lpw-j4.js} +1 -1
  330. package/dist/ui/index.html +3 -3
  331. package/dist/utils/constants.d.ts +2 -2
  332. package/dist/utils/constants.js +1 -1
  333. package/dist/utils/contextAttachmentUpload.d.ts +2 -0
  334. package/dist/utils/contextAttachmentUpload.js +7 -0
  335. package/dist/utils/contextFiles.d.ts +1 -1
  336. package/dist/utils/contextFiles.js +4 -4
  337. package/dist/utils/taskActivity.d.ts +3 -2
  338. package/dist/utils/taskActivity.js +19 -2
  339. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  340. package/dist/utils/taskEditorReconciliation.js +217 -0
  341. package/dist/utils/taskNormalization.d.ts +1 -0
  342. package/dist/utils/taskNormalization.js +39 -0
  343. package/dist/utils/taskSearch.js +2 -2
  344. package/dist/utils/uiNotice.d.ts +4 -0
  345. package/package.json +21 -4
  346. package/dist/ui/assets/AiProfilesModule-DPxQeF9N.js +0 -1
  347. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  348. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DHNYaNg6.js +0 -3
  349. package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
  350. package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
  351. package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
  352. package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
  353. package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
  354. package/dist/ui/assets/PlansPage-BVH_NfgT.js +0 -1
  355. package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
  356. package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
  357. package/dist/ui/assets/TaskSettings-xVsxSa0g.js +0 -12
  358. package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
  359. package/dist/ui/assets/index-BzJlVnNS.css +0 -1
  360. package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
@@ -0,0 +1,140 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ const DEFAULT_POOL_SIZE = 2;
3
+ const MAX_POOL_SIZE = 8;
4
+ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
5
+ function positiveInteger(value, fallback) {
6
+ if (!Number.isFinite(value) || Number(value) <= 0)
7
+ return fallback;
8
+ return Math.max(1, Math.floor(Number(value)));
9
+ }
10
+ export class CloudCollectionReadPool {
11
+ slots = [];
12
+ queue = [];
13
+ requestTimeoutMs;
14
+ desiredSize;
15
+ workerData;
16
+ workerFactory;
17
+ nextRequestId = 1;
18
+ closing = false;
19
+ constructor(options) {
20
+ this.requestTimeoutMs = positiveInteger(options.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS);
21
+ this.workerData = {
22
+ projectRoot: options.projectRoot,
23
+ tenantId: options.tenantId,
24
+ connectionString: options.connectionString,
25
+ };
26
+ this.workerFactory = options.workerFactory || (() => new Worker(new URL('./cloudCollectionReadWorker.js', import.meta.url), { workerData: this.workerData }));
27
+ this.desiredSize = Math.min(MAX_POOL_SIZE, positiveInteger(options.size, DEFAULT_POOL_SIZE));
28
+ }
29
+ execute(request) {
30
+ if (this.closing) {
31
+ return Promise.reject(new Error('[Taskforce] Cloud collection read pool is closed.'));
32
+ }
33
+ this.ensureSlots();
34
+ return new Promise((resolve, reject) => {
35
+ this.queue.push({ request, resolve, reject });
36
+ this.pump();
37
+ });
38
+ }
39
+ async close() {
40
+ if (this.closing)
41
+ return;
42
+ this.closing = true;
43
+ const closedError = new Error('[Taskforce] Cloud collection read pool closed before the request completed.');
44
+ for (const pending of this.queue.splice(0))
45
+ pending.reject(closedError);
46
+ await Promise.all(this.slots.splice(0).map(async (slot) => {
47
+ if (slot.active) {
48
+ clearTimeout(slot.active.timeout);
49
+ slot.active.reject(closedError);
50
+ slot.active = null;
51
+ }
52
+ slot.worker.postMessage({ type: 'close' });
53
+ await slot.worker.terminate();
54
+ }));
55
+ }
56
+ spawnSlot() {
57
+ if (this.closing)
58
+ return;
59
+ const worker = this.workerFactory();
60
+ const slot = { worker, ready: false, active: null };
61
+ this.slots.push(slot);
62
+ worker.on('message', (message) => this.handleMessage(slot, message));
63
+ worker.on('error', (error) => this.handleWorkerFailure(slot, error instanceof Error ? error : new Error(String(error))));
64
+ worker.on('exit', (code) => {
65
+ if (!this.closing && this.slots.includes(slot)) {
66
+ this.handleWorkerFailure(slot, new Error(`[Taskforce] Cloud collection read worker exited with code ${code}.`));
67
+ }
68
+ });
69
+ }
70
+ handleMessage(slot, message) {
71
+ if (message.type === 'ready') {
72
+ slot.ready = true;
73
+ this.ensureSlots();
74
+ this.pump();
75
+ return;
76
+ }
77
+ const active = slot.active;
78
+ if (!active || active.requestId !== message.requestId)
79
+ return;
80
+ clearTimeout(active.timeout);
81
+ slot.active = null;
82
+ if (message.type === 'result')
83
+ active.resolve(message.response);
84
+ else
85
+ active.reject(new Error(message.error || '[Taskforce] Cloud collection read worker failed.'));
86
+ this.pump();
87
+ }
88
+ handleWorkerFailure(slot, error) {
89
+ const slotIndex = this.slots.indexOf(slot);
90
+ if (slotIndex < 0)
91
+ return;
92
+ this.slots.splice(slotIndex, 1);
93
+ if (slot.active) {
94
+ clearTimeout(slot.active.timeout);
95
+ slot.active.reject(error);
96
+ slot.active = null;
97
+ }
98
+ void slot.worker.terminate();
99
+ if (!this.closing && this.slots.length === 0) {
100
+ for (const pending of this.queue.splice(0))
101
+ pending.reject(error);
102
+ }
103
+ this.pump();
104
+ }
105
+ ensureSlots() {
106
+ if (this.closing)
107
+ return;
108
+ if (this.slots.some((slot) => !slot.ready))
109
+ return;
110
+ if (this.slots.length < this.desiredSize)
111
+ this.spawnSlot();
112
+ }
113
+ pump() {
114
+ if (this.closing || this.queue.length === 0)
115
+ return;
116
+ for (const slot of this.slots) {
117
+ if (!slot.ready || slot.active || this.queue.length === 0)
118
+ continue;
119
+ const pending = this.queue.shift();
120
+ const requestId = this.nextRequestId++;
121
+ const timeout = setTimeout(() => {
122
+ this.handleWorkerFailure(slot, new Error(`[Taskforce] Cloud collection read worker timed out after ${this.requestTimeoutMs}ms.`));
123
+ }, this.requestTimeoutMs);
124
+ timeout.unref?.();
125
+ slot.active = { ...pending, requestId, timeout };
126
+ slot.worker.postMessage({ type: 'execute', requestId, request: pending.request });
127
+ }
128
+ }
129
+ }
130
+ export function resolveCloudCollectionReadPoolSize(env = process.env) {
131
+ if (String(env.TASKFORCE_CLOUD_READ_WORKERS || '').trim() === '0')
132
+ return 0;
133
+ return Math.min(MAX_POOL_SIZE, positiveInteger(Number(env.TASKFORCE_CLOUD_READ_WORKERS), DEFAULT_POOL_SIZE));
134
+ }
135
+ export function shouldUseCloudCollectionReadPool(input) {
136
+ return input.runtimeMode === 'cloud'
137
+ && input.databaseProvider === 'postgres'
138
+ && Boolean(String(input.connectionString || '').trim())
139
+ && input.workerCount > 0;
140
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ import { parentPort, workerData } from 'node:worker_threads';
2
+ import { TaskforceCore } from '../core/Taskforce.js';
3
+ import { executeCloudCollectionRead, } from './cloudCollectionRead.js';
4
+ if (!parentPort) {
5
+ throw new Error('[Taskforce] Cloud collection read worker requires a parent port.');
6
+ }
7
+ const config = workerData;
8
+ const core = new TaskforceCore({
9
+ projectRoot: config.projectRoot,
10
+ tenantId: config.tenantId,
11
+ runtimeMode: 'cloud',
12
+ initializationMode: 'cloud-read-worker',
13
+ database: {
14
+ provider: 'postgres',
15
+ connectionString: config.connectionString,
16
+ },
17
+ });
18
+ parentPort.on('message', (message) => {
19
+ if (message.type === 'close') {
20
+ core.close();
21
+ parentPort?.close();
22
+ return;
23
+ }
24
+ try {
25
+ const response = executeCloudCollectionRead(core, message.request);
26
+ parentPort?.postMessage({ type: 'result', requestId: message.requestId, response });
27
+ }
28
+ catch (error) {
29
+ parentPort?.postMessage({
30
+ type: 'error',
31
+ requestId: message.requestId,
32
+ error: error instanceof Error ? error.message : String(error),
33
+ });
34
+ }
35
+ });
36
+ parentPort.postMessage({ type: 'ready' });
@@ -6,8 +6,9 @@
6
6
  */
7
7
  import * as http from 'http';
8
8
  import { WebSocketServer } from 'ws';
9
- import { TaskforceCore } from '../core/Taskforce.js';
10
- import type { RequestAccessContext } from './auth.js';
9
+ export { resolveAuthorizedWorkspaceAccess, resolveDisabledAccessError, isWorkspaceAccessRecoveryRoute, } from './authorizedWorkspaceAccess.js';
10
+ import type { LocalServiceCloudTarget } from '../config/localServiceCloudTarget.js';
11
+ import type { LocalServiceRuntimeContract } from '../config/localServiceRuntimeContract.js';
11
12
  import type { LocalSyncCoordinatorHost } from '../sync/coordinator/localSyncCoordinatorHost.js';
12
13
  import type { LocalSyncProcessLock } from '../sync/coordinator/localSyncProcessLock.js';
13
14
  import type { LocalDataOwnerPermit } from './localDataOwnerPermit.js';
@@ -25,6 +26,8 @@ export interface StandaloneServerOptions {
25
26
  ownerPid: number;
26
27
  bootstrapCapability: string;
27
28
  ownershipKey: string;
29
+ cloudTarget: LocalServiceCloudTarget;
30
+ runtimeContract: LocalServiceRuntimeContract;
28
31
  };
29
32
  }
30
33
  export interface TaskforceStandaloneServer extends http.Server {
@@ -45,17 +48,10 @@ export declare const TASKFORCE_PROXY_ORIGIN_PROTO_HEADER = "x-taskforce-origin-p
45
48
  export declare const TASKFORCE_PROXY_ORIGIN_BASE_URL_HEADER = "x-taskforce-origin-base-url";
46
49
  export declare const TASKFORCE_PROXY_ORIGIN_RUNTIME_HEADER = "x-taskforce-origin-runtime";
47
50
  export declare const TASKFORCE_PROXY_CLOUD_ENVIRONMENT_HEADER = "x-taskforce-cloud-environment";
48
- interface AuthorizedRequestAccess extends RequestAccessContext {
49
- disabled?: boolean;
50
- accountDisabled?: boolean;
51
- workspaceDisabled?: boolean;
52
- }
53
- export declare function isWorkspaceAccessRecoveryRoute(pathname: string): boolean;
54
- export declare function resolveDisabledAccessError(access: Pick<AuthorizedRequestAccess, 'disabled' | 'accountDisabled' | 'workspaceDisabled'>, pathname: string): string | null;
51
+ export declare function sanitizeQaRunIdHeader(raw: unknown): string;
55
52
  export declare function shouldProxyCloudPath(pathname: string): boolean;
56
53
  export declare function shouldProxyCloudRequest(url: Pick<URL, 'pathname' | 'searchParams'>, env?: NodeJS.ProcessEnv): boolean;
57
54
  export declare function resolveCloudProxyUpstreamBaseUrl(req: http.IncomingMessage, fallbackBaseUrl: string): string;
58
- export declare function resolveAuthorizedWorkspaceAccess(core: Pick<TaskforceCore, 'resolveUserAccess' | 'getSystemRole'>, access: AuthorizedRequestAccess, requestedWorkspaceId: string): AuthorizedRequestAccess;
59
55
  export declare function shouldApplyReadOnlyMutationGuard(methodRaw: string | undefined, pathname: string): boolean;
60
56
  export declare function resolveEffectiveRequestUserId(accessUserId: string, explicitUserId: string): string;
61
57
  export declare function resolveMaxPayloadBytesForPath(pathname: string, defaultMaxBytes: number): number;
@@ -72,4 +68,3 @@ export declare function ensurePublicPricingAuthExclusion(excludedPaths: string[]
72
68
  export declare function ensurePublicSiteConfigAuthExclusion(excludedPaths: string[]): string[];
73
69
  export declare function isBillingWebhookPath(pathname: string): boolean;
74
70
  export declare function createStandaloneServer(options: StandaloneServerOptions): TaskforceStandaloneServer;
75
- export {};
@@ -14,9 +14,12 @@ import chokidar from 'chokidar';
14
14
  import { TaskforceCore } from '../core/Taskforce.js';
15
15
  import { createRoutes, matchRoute } from './routes.js';
16
16
  import { formatApiErrorResponse } from './routes/primitives.js';
17
+ import { logSlowBootstrapRoute } from './routes/shared.js';
17
18
  import { applyCorsHeaders, getAllowedOriginsFromEnv } from './cors.js';
18
- import { applyPrefixedRateLimitHeaders, applyRateLimitHeaders, InMemoryRateLimiter, resolveRateLimitKey } from './rateLimit.js';
19
+ import { applyPrefixedRateLimitHeaders, applyRateLimitHeaders, InMemoryRateLimiter, isWorkspaceSyncFeedRead, resolveRateLimitKey, } from './rateLimit.js';
19
20
  import { isRequestAuthorized, resolveAuthConfigFromEnv, resolveRequestAccess } from './auth.js';
21
+ import { resolveAuthorizedWorkspaceAccess, resolveDisabledAccessError, } from './authorizedWorkspaceAccess.js';
22
+ export { resolveAuthorizedWorkspaceAccess, resolveDisabledAccessError, isWorkspaceAccessRecoveryRoute, } from './authorizedWorkspaceAccess.js';
20
23
  import { assertCloudDatabaseProvider, resolveRuntimeModeFromEnv } from './runtimeMode.js';
21
24
  import { applySecurityHeaders } from './securityHeaders.js';
22
25
  import { resolveDatabaseConfigFromEnv } from '../storage/providerConfig.js';
@@ -37,6 +40,8 @@ import { createWorkspaceSyncServerComposition, shutdownWorkspaceSyncServerCompos
37
40
  import { LocalServiceSessionManager } from './localServiceSessions.js';
38
41
  import { LocalSyncIdentityStore } from '../sync/v3/localSyncIdentityStore.js';
39
42
  import { shouldBroadcastLocalFileInvalidation } from './localRealtimeFileInvalidation.js';
43
+ import { resolveCloudCollectionReadOperation, } from './cloudCollectionRead.js';
44
+ import { CloudCollectionReadPool, resolveCloudCollectionReadPoolSize, shouldUseCloudCollectionReadPool, } from './cloudCollectionReadPool.js';
40
45
  const __filename = fileURLToPath(import.meta.url);
41
46
  const __dirname = path.dirname(__filename);
42
47
  const MIME_TYPES = {
@@ -173,20 +178,11 @@ export const TASKFORCE_PROXY_ORIGIN_PROTO_HEADER = 'x-taskforce-origin-proto';
173
178
  export const TASKFORCE_PROXY_ORIGIN_BASE_URL_HEADER = 'x-taskforce-origin-base-url';
174
179
  export const TASKFORCE_PROXY_ORIGIN_RUNTIME_HEADER = 'x-taskforce-origin-runtime';
175
180
  export const TASKFORCE_PROXY_CLOUD_ENVIRONMENT_HEADER = 'x-taskforce-cloud-environment';
176
- export function isWorkspaceAccessRecoveryRoute(pathname) {
177
- return pathname === '/api/taskforce/workspaces'
178
- || pathname === '/api/taskforce/session/workspace';
179
- }
180
- export function resolveDisabledAccessError(access, pathname) {
181
- if (pathname.startsWith('/api/taskforce/auth/'))
182
- return null;
183
- if (access.accountDisabled ?? access.disabled) {
184
- return 'Forbidden: user account is disabled.';
185
- }
186
- if (access.workspaceDisabled && !isWorkspaceAccessRecoveryRoute(pathname)) {
187
- return 'Forbidden: workspace access is not active for this user.';
188
- }
189
- return null;
181
+ export function sanitizeQaRunIdHeader(raw) {
182
+ const normalized = String(Array.isArray(raw) ? raw[0] : raw || '')
183
+ .trim()
184
+ .replace(/[^A-Za-z0-9._-]+/g, '-');
185
+ return normalized.slice(0, 128) || '-';
190
186
  }
191
187
  function shouldLogRefreshDiagnostic(pathname) {
192
188
  return REFRESH_DIAGNOSTIC_PATH_PREFIXES.some((prefix) => pathname === prefix || pathname.startsWith(prefix));
@@ -301,31 +297,6 @@ export function resolveCloudProxyUpstreamBaseUrl(req, fallbackBaseUrl) {
301
297
  return fallbackBaseUrl;
302
298
  return TASKFORCE_CLOUD_ENVIRONMENTS[requestedEnvironment].appBaseUrl;
303
299
  }
304
- export function resolveAuthorizedWorkspaceAccess(core, access, requestedWorkspaceId) {
305
- if (!access.authenticated || !access.userId || access.userId === 'anonymous')
306
- return access;
307
- const trimmedRequestedWorkspaceId = String(requestedWorkspaceId || '').trim();
308
- const candidateWorkspaceIds = [
309
- trimmedRequestedWorkspaceId,
310
- String(access.workspaceId || '').trim()
311
- ].filter((workspaceId, index, values) => Boolean(workspaceId) && values.indexOf(workspaceId) === index);
312
- for (const workspaceId of candidateWorkspaceIds) {
313
- const resolved = core.resolveUserAccess(access.userId, workspaceId, access.role);
314
- if (!resolved)
315
- continue;
316
- return {
317
- ...access,
318
- role: resolved.role,
319
- workspaceId: resolved.workspaceId,
320
- userId: resolved.userId,
321
- systemRole: core.getSystemRole(resolved.userId),
322
- disabled: resolved.disabled,
323
- accountDisabled: resolved.accountDisabled ?? resolved.disabled,
324
- workspaceDisabled: resolved.workspaceDisabled ?? false
325
- };
326
- }
327
- return access;
328
- }
329
300
  export function shouldApplyReadOnlyMutationGuard(methodRaw, pathname) {
330
301
  const method = String(methodRaw || 'GET').toUpperCase();
331
302
  if (method !== 'POST' && method !== 'PATCH' && method !== 'DELETE')
@@ -673,16 +644,33 @@ export function createStandaloneServer(options) {
673
644
  },
674
645
  } : undefined,
675
646
  });
647
+ const cloudCollectionReadWorkerCount = resolveCloudCollectionReadPoolSize(process.env);
648
+ const cloudCollectionReadPool = shouldUseCloudCollectionReadPool({
649
+ runtimeMode,
650
+ databaseProvider: db.provider,
651
+ connectionString: db.connectionString,
652
+ workerCount: cloudCollectionReadWorkerCount,
653
+ })
654
+ ? new CloudCollectionReadPool({
655
+ projectRoot: options.projectRoot,
656
+ tenantId: core.getTenantId(),
657
+ connectionString: db.connectionString,
658
+ size: cloudCollectionReadWorkerCount,
659
+ })
660
+ : null;
676
661
  const allowedOrigins = getAllowedOriginsFromEnv(process.env.TASKFORCE_ALLOWED_ORIGINS, runtimeMode);
677
662
  const rateLimitEnabled = typeof process.env.TASKFORCE_API_RATE_LIMIT_ENABLED === 'string'
678
663
  ? process.env.TASKFORCE_API_RATE_LIMIT_ENABLED !== 'false'
679
664
  : (runtimeMode === 'cloud');
680
665
  const rateLimitLimit = Number.parseInt(process.env.TASKFORCE_API_RATE_LIMIT_MAX_REQUESTS || '', 10) || 120;
681
666
  const rateLimitWindowMs = Number.parseInt(process.env.TASKFORCE_API_RATE_LIMIT_WINDOW_MS || '', 10) || 60_000;
667
+ const syncFeedRateLimit = Number.parseInt(process.env.TASKFORCE_SYNC_FEED_RATE_LIMIT_MAX_REQUESTS || '', 10) || 600;
668
+ const syncFeedRateLimitWindowMs = Number.parseInt(process.env.TASKFORCE_SYNC_FEED_RATE_LIMIT_WINDOW_MS || '', 10) || 60_000;
682
669
  const webhookRateLimitMaxRequests = Number.parseInt(process.env.TASKFORCE_STRIPE_WEBHOOK_RATE_LIMIT_MAX_REQUESTS || '', 10) || 600;
683
670
  const webhookRateLimitWindowMs = Number.parseInt(process.env.TASKFORCE_STRIPE_WEBHOOK_RATE_LIMIT_WINDOW_MS || '', 10) || 60_000;
684
671
  const maxPayloadBytes = Number.parseInt(process.env.TASKFORCE_MAX_PAYLOAD_BYTES || '', 10) || 1_048_576;
685
672
  const rateLimiter = new InMemoryRateLimiter(rateLimitLimit, rateLimitWindowMs);
673
+ const syncFeedRateLimiter = new InMemoryRateLimiter(syncFeedRateLimit, syncFeedRateLimitWindowMs);
686
674
  const webhookRateLimiter = new InMemoryRateLimiter(webhookRateLimitMaxRequests, webhookRateLimitWindowMs);
687
675
  const resolveAuthRateLimitSettings = () => {
688
676
  const auth = core.getGlobalSettings().auth || {};
@@ -786,7 +774,8 @@ export function createStandaloneServer(options) {
786
774
  const requestId = String(req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || '-';
787
775
  const workspaceId = String(req.headers['x-taskforce-workspace-id'] || '').trim() || '-';
788
776
  const userId = String(req.headers['x-taskforce-user-id'] || '').trim() || '-';
789
- console.info(`[Taskforce RefreshDiag] method=${method} path=${pathname} status=${statusCode} durationMs=${durationMs} requestId=${requestId} workspaceId=${workspaceId} userId=${userId}`);
777
+ const qaRunId = sanitizeQaRunIdHeader(req.headers['x-taskforce-qa-run-id']);
778
+ console.info(`[Taskforce RefreshDiag] method=${method} path=${pathname} status=${statusCode} durationMs=${durationMs} requestId=${requestId} workspaceId=${workspaceId} userId=${userId} qaRunId=${qaRunId}`);
790
779
  };
791
780
  // Resolve static files directory at runtime
792
781
  // Standalone UI source now lives in apps/app and builds to dist/ui.
@@ -1013,7 +1002,9 @@ export function createStandaloneServer(options) {
1013
1002
  });
1014
1003
  const rateLimitResult = isBillingWebhook
1015
1004
  ? webhookRateLimiter.check(key)
1016
- : rateLimiter.check(key);
1005
+ : isWorkspaceSyncFeedRead(req.method, url.pathname)
1006
+ ? syncFeedRateLimiter.check(key)
1007
+ : rateLimiter.check(key);
1017
1008
  if (isBillingWebhook) {
1018
1009
  applyPrefixedRateLimitHeaders(res, rateLimitResult, 'X-Webhook-RateLimit');
1019
1010
  }
@@ -1066,6 +1057,39 @@ export function createStandaloneServer(options) {
1066
1057
  res.end(JSON.stringify({ error: auth.reason || 'Unauthorized' }));
1067
1058
  return;
1068
1059
  }
1060
+ const cloudCollectionReadOperation = cloudCollectionReadPool
1061
+ ? resolveCloudCollectionReadOperation(req.method, url.pathname)
1062
+ : null;
1063
+ if (cloudCollectionReadPool && cloudCollectionReadOperation) {
1064
+ try {
1065
+ const requestedWorkspaceId = Array.isArray(req.headers['x-taskforce-workspace-id'])
1066
+ ? String(req.headers['x-taskforce-workspace-id'][0] || '')
1067
+ : String(req.headers['x-taskforce-workspace-id'] || '');
1068
+ const response = await cloudCollectionReadPool.execute({
1069
+ operation: cloudCollectionReadOperation,
1070
+ pathname: url.pathname,
1071
+ requestedWorkspaceId,
1072
+ access: accessForRateLimit,
1073
+ performanceTrace: String(req.headers['x-taskforce-performance-trace'] || '').trim() === '1',
1074
+ });
1075
+ if (response.performance) {
1076
+ logSlowBootstrapRoute({
1077
+ route: url.pathname,
1078
+ workspaceId: response.workspaceId,
1079
+ traceId: String(req.headers['x-taskforce-bootstrap-trace-id'] || '').trim(),
1080
+ durationMs: response.performance.durationMs,
1081
+ details: response.performance.details,
1082
+ });
1083
+ }
1084
+ response.headers['X-Taskforce-Cloud-Read-Execution'] = 'worker';
1085
+ res.writeHead(response.statusCode, response.headers);
1086
+ res.end(response.body);
1087
+ return;
1088
+ }
1089
+ catch (error) {
1090
+ console.error(`[Taskforce] Cloud collection read worker failed; using synchronous fallback path=${url.pathname}:`, error instanceof Error ? error.message : String(error));
1091
+ }
1092
+ }
1069
1093
  const pathname = url.pathname;
1070
1094
  const isMutation = shouldApplyReadOnlyMutationGuard(req.method, pathname);
1071
1095
  let access = accessForRateLimit;
@@ -1203,6 +1227,7 @@ export function createStandaloneServer(options) {
1203
1227
  if (serverResult.status === 'rejected') {
1204
1228
  throw serverResult.reason;
1205
1229
  }
1230
+ await cloudCollectionReadPool?.close();
1206
1231
  },
1207
1232
  closeCore: () => core.close(),
1208
1233
  });
@@ -1,3 +1,5 @@
1
+ import { type LocalServiceCloudTarget } from '../config/localServiceCloudTarget.js';
2
+ import { type LocalServiceRuntimeContract } from '../config/localServiceRuntimeContract.js';
1
3
  import { type WindowsAclCommandRunner } from './localServiceWindowsAcl.js';
2
4
  export interface LocalServiceDescriptor {
3
5
  schemaVersion: 1;
@@ -9,6 +11,8 @@ export interface LocalServiceDescriptor {
9
11
  generation: string;
10
12
  bootstrapCapability: string;
11
13
  publishedAt: string;
14
+ cloudTarget?: LocalServiceCloudTarget | null;
15
+ runtimeContract?: LocalServiceRuntimeContract | null;
12
16
  }
13
17
  export interface LocalServiceLeaseIdentityInput {
14
18
  projectRoot: string;
@@ -27,6 +31,8 @@ export interface LocalServiceDescriptorPublication {
27
31
  endpoint: string;
28
32
  protocolVersion: string;
29
33
  appVersion: string;
34
+ cloudTarget: LocalServiceCloudTarget;
35
+ runtimeContract: LocalServiceRuntimeContract;
30
36
  }
31
37
  export interface LocalServiceLease {
32
38
  readonly identity: LocalServiceLeaseIdentity;
@@ -3,6 +3,8 @@ import * as fs from 'fs';
3
3
  import * as net from 'net';
4
4
  import * as os from 'os';
5
5
  import * as path from 'path';
6
+ import { parseLocalServiceCloudTarget, } from '../config/localServiceCloudTarget.js';
7
+ import { parseLocalServiceRuntimeContract, } from '../config/localServiceRuntimeContract.js';
6
8
  import { resolveLocalSyncProcessLockIdentity } from './localDatabaseIdentity.js';
7
9
  import { ensureWindowsUserOnlyDirectoryAcl, } from './localServiceWindowsAcl.js';
8
10
  const DESCRIPTOR_SCHEMA_VERSION = 1;
@@ -161,8 +163,20 @@ function parseDescriptor(value, ownershipKey) {
161
163
  || typeof value.publishedAt !== 'string') {
162
164
  throw new Error('Local service descriptor is invalid.');
163
165
  }
166
+ const cloudTarget = value.cloudTarget == null
167
+ ? null
168
+ : parseLocalServiceCloudTarget(value.cloudTarget);
169
+ if (value.cloudTarget != null && !cloudTarget) {
170
+ throw new Error('Local service descriptor cloud target is invalid.');
171
+ }
172
+ const runtimeContract = value.runtimeContract == null
173
+ ? null
174
+ : parseLocalServiceRuntimeContract(value.runtimeContract);
175
+ if (value.runtimeContract != null && !runtimeContract) {
176
+ throw new Error('Local service descriptor runtime contract is invalid.');
177
+ }
164
178
  assertLoopbackEndpoint(value.endpoint);
165
- return value;
179
+ return { ...value, cloudTarget, runtimeContract };
166
180
  }
167
181
  function readOptionalDescriptor(identity) {
168
182
  try {
@@ -363,6 +377,8 @@ export async function acquireLocalServiceLease(input, dependencies = {}) {
363
377
  generation,
364
378
  bootstrapCapability,
365
379
  publishedAt: (dependencies.now?.() || new Date()).toISOString(),
380
+ cloudTarget: publication.cloudTarget,
381
+ runtimeContract: publication.runtimeContract,
366
382
  };
367
383
  publishJsonFileAtomically(identity.descriptorPath, descriptor, platform);
368
384
  return descriptor;
@@ -15,6 +15,7 @@ import { createWorkspaceSyncEngineServerRunnerOperations } from '../sync/engine/
15
15
  import { workspaceSyncTransferEvidenceEvent } from '../sync/engine/workspaceSyncTransferEvidence.js';
16
16
  import { createWorkspaceSyncEngineServerPushCandidateProvider, createWorkspaceSyncEngineServerSnapshotReader, } from '../sync/engine/workspaceSyncEngineServerSnapshotReader.js';
17
17
  import { readWorkspaceSyncLocalOwnershipSnapshot } from '../sync/v3/workspaceSyncLocalOwnershipSnapshot.js';
18
+ import { resolveRequestedCombinedFeedCoverage } from '../sync/v3/combinedFeedCapability.js';
18
19
  import { resolveWorkspaceSyncV3CombinedWireContract, } from '../sync/v3/workspaceSyncV3CombinedWireContract.js';
19
20
  import { LocalWorkspaceSyncServerOutboxDispatcher, } from '../sync/v3/localWorkspaceSyncServerOutboxDispatcher.js';
20
21
  import { readWorkspaceSyncV3LocalOutboxStatus, } from '../sync/v3/workspaceSyncV3LocalOutboxStatus.js';
@@ -950,15 +951,21 @@ export class LocalWorkspaceSyncServerRuntime {
950
951
  if (combined.owner === 'v3' && !combinedContract) {
951
952
  throw Object.assign(new Error('The persisted combined-feed ownership contract is invalid.'), { code: 'SYNC_RUNNER_V3_OWNERSHIP_INVALID' });
952
953
  }
954
+ const desiredCombinedCoverage = combined.owner === 'v3'
955
+ ? resolveRequestedCombinedFeedCoverage(this.options.env || process.env)
956
+ : null;
957
+ const desiredCombinedContract = desiredCombinedCoverage
958
+ ? resolveWorkspaceSyncV3CombinedWireContract(desiredCombinedCoverage)
959
+ : null;
953
960
  return {
954
961
  initiativeFeedActivationEnabled: ownership.initiativeProjection.owner === 'v3',
955
962
  initiativeProjection: ownership.initiativeProjection,
956
963
  combinedFeedActivationEnabled: combined.owner === 'v3',
957
964
  combinedProjection: combined,
958
- ...(combinedContract
965
+ ...(combinedContract && desiredCombinedContract
959
966
  ? {
960
- combinedFeedCoverage: combinedContract.coverage,
961
- combinedFeedExcludedProjections: combinedContract.excludedProjections,
967
+ combinedFeedCoverage: desiredCombinedContract.coverage,
968
+ combinedFeedExcludedProjections: desiredCombinedContract.excludedProjections,
962
969
  }
963
970
  : {}),
964
971
  };
@@ -26,5 +26,6 @@ export declare function resolveRateLimitKey(params: {
26
26
  sessionId?: string | null;
27
27
  userId?: string | null;
28
28
  }): string;
29
+ export declare function isWorkspaceSyncFeedRead(method: string | undefined, pathname: string): boolean;
29
30
  export declare function applyRateLimitHeaders(res: ServerResponse, result: RateLimitResult): void;
30
31
  export declare function applyPrefixedRateLimitHeaders(res: ServerResponse, result: RateLimitResult, prefix: string): void;
@@ -97,6 +97,10 @@ export function resolveRateLimitKey(params) {
97
97
  }
98
98
  return `ip:${ip}:${method}:${route}`;
99
99
  }
100
+ export function isWorkspaceSyncFeedRead(method, pathname) {
101
+ return String(method || 'GET').trim().toUpperCase() === 'GET'
102
+ && pathname === '/api/taskforce/sync/v3/workspace/feed';
103
+ }
100
104
  export function applyRateLimitHeaders(res, result) {
101
105
  res.setHeader('X-RateLimit-Limit', String(result.limit));
102
106
  res.setHeader('X-RateLimit-Remaining', String(result.remaining));
@@ -68,23 +68,34 @@ export function createRealtimeSyncWsManager(core, authConfig, logger = console,
68
68
  }
69
69
  connections.delete(ws);
70
70
  };
71
- const canSubscribe = (state, workspaceId) => {
71
+ const resolveSubscriptionAccess = (state, workspaceId) => {
72
72
  if (!workspaceId)
73
- return false;
73
+ return 'forbidden';
74
74
  if (!authConfig.enabled || !authConfig.requiredForApi)
75
- return true;
75
+ return 'allowed';
76
76
  if (!state.authenticated || !state.userId || state.userId === 'anonymous')
77
- return false;
78
- const resolved = core.resolveUserAccess(state.userId, workspaceId, state.role);
79
- return Boolean(resolved?.workspaceId === workspaceId);
77
+ return 'forbidden';
78
+ try {
79
+ const resolved = core.resolveUserAccess(state.userId, workspaceId, state.role);
80
+ return resolved?.workspaceId === workspaceId ? 'allowed' : 'forbidden';
81
+ }
82
+ catch (error) {
83
+ logger.warn(`[Taskforce] WebSocket access check unavailable workspace=${workspaceId}: ${String(error instanceof Error ? error.message : error)}`);
84
+ return 'unavailable';
85
+ }
80
86
  };
81
87
  const closeUnauthorized = (ws, reason) => {
82
88
  logger.warn(`[Taskforce] WebSocket rejected: ${reason}`);
83
89
  ws.close(1008, reason);
84
90
  };
85
91
  const subscribeWorkspace = (ws, state, workspaceId) => {
86
- if (!canSubscribe(state, workspaceId)) {
87
- send(ws, { type: 'taskforce:subscription-error', workspaceId, reason: 'forbidden' });
92
+ const accessDecision = resolveSubscriptionAccess(state, workspaceId);
93
+ if (accessDecision !== 'allowed') {
94
+ send(ws, {
95
+ type: 'taskforce:subscription-error',
96
+ workspaceId,
97
+ reason: accessDecision === 'unavailable' ? 'temporarily-unavailable' : 'forbidden'
98
+ });
88
99
  return;
89
100
  }
90
101
  state.workspaceIds.add(workspaceId);
@@ -132,8 +143,13 @@ export function createRealtimeSyncWsManager(core, authConfig, logger = console,
132
143
  send(ws, { type: 'taskforce:replay-error', reason: 'workspace-required' });
133
144
  return;
134
145
  }
135
- if (!canSubscribe(state, workspaceId)) {
136
- send(ws, { type: 'taskforce:replay-error', workspaceId, reason: 'forbidden' });
146
+ const accessDecision = resolveSubscriptionAccess(state, workspaceId);
147
+ if (accessDecision !== 'allowed') {
148
+ send(ws, {
149
+ type: 'taskforce:replay-error',
150
+ workspaceId,
151
+ reason: accessDecision === 'unavailable' ? 'temporarily-unavailable' : 'forbidden'
152
+ });
137
153
  return;
138
154
  }
139
155
  state.workspaceIds.add(workspaceId);
@@ -191,8 +207,16 @@ export function createRealtimeSyncWsManager(core, authConfig, logger = console,
191
207
  connections.set(ws, state);
192
208
  logger.log(`[Taskforce] WebSocket client connected user=${state.userId}`);
193
209
  const initialWorkspaceId = parseWorkspaceId(access.workspaceId);
194
- if (initialWorkspaceId && canSubscribe(state, initialWorkspaceId)) {
195
- state.workspaceIds.add(initialWorkspaceId);
210
+ if (initialWorkspaceId) {
211
+ const accessDecision = resolveSubscriptionAccess(state, initialWorkspaceId);
212
+ if (accessDecision === 'unavailable') {
213
+ ws.close(1013, 'access-unavailable');
214
+ removeConnection(ws);
215
+ return;
216
+ }
217
+ if (accessDecision === 'allowed') {
218
+ state.workspaceIds.add(initialWorkspaceId);
219
+ }
196
220
  }
197
221
  ws.on('message', (rawData) => {
198
222
  const payload = parseJson(rawData);
@@ -1953,6 +1953,7 @@ export function registerAdminRoutes(deps) {
1953
1953
  workspaceAssetStore,
1954
1954
  publishedContentResolver,
1955
1955
  repairMissingAssetLinks: true,
1956
+ repairMissingContentFiles: body?.repairMissingContentFiles === true,
1956
1957
  aiProfiles: typeof core.listAiProfiles === 'function'
1957
1958
  ? core.listAiProfiles(workspaceId, { includeArchived: true }) || []
1958
1959
  : [],
@@ -1,4 +1,5 @@
1
- import { TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY, resolveAppGateAccess, } from '../../runtime/appGates.js';
1
+ import { TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY, } from '../../runtime/appGates.js';
2
+ import { resolveNodeAppGateAccess } from '../../runtime/nodeAppGates.js';
2
3
  import { AgentRoleDefinitionValidationError } from '../../shared/agentRoleDefinition.js';
3
4
  import { AgentRoleConflictError, AgentRoleNotFoundError, AgentRoleRetiredError, AgentRoleStore, } from '../../storage/agentRoleStore.js';
4
5
  import { parseJsonBody } from './primitives.js';
@@ -128,7 +129,7 @@ export function registerAgentRolesRoutes(deps) {
128
129
  const guard = (req, res) => {
129
130
  if (!ensureAppAccess(req, res))
130
131
  return false;
131
- const gate = resolveAppGateAccess(TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY);
132
+ const gate = resolveNodeAppGateAccess(TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY);
132
133
  if (gate.allowed)
133
134
  return true;
134
135
  writeJson(res, 403, {
@@ -1,4 +1,5 @@
1
- import { TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY, resolveAppGateAccess, } from '../../runtime/appGates.js';
1
+ import { TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY, } from '../../runtime/appGates.js';
2
+ import { resolveNodeAppGateAccess } from '../../runtime/nodeAppGates.js';
2
3
  import { compileTaskforceAgentSkillPrompt } from '../../shared/taskforceAgentSkill.js';
3
4
  import { TaskforceAgentStore } from '../../storage/taskforceAgentStore.js';
4
5
  import { TaskforceAgentSkillConflictError, TaskforceAgentSkillStore, } from '../../storage/taskforceAgentSkillStore.js';
@@ -73,7 +74,7 @@ export function registerAgentSkillsRoutes(deps) {
73
74
  const ensureFeatureAccess = (req, res) => {
74
75
  if (!ensureAppAccess(req, res))
75
76
  return false;
76
- const gate = resolveAppGateAccess(TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY);
77
+ const gate = resolveNodeAppGateAccess(TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY);
77
78
  if (gate.allowed)
78
79
  return true;
79
80
  writeJson(res, 403, {