@taskforcehq/taskforce 0.3.305 → 0.3.307

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 (440) hide show
  1. package/README.md +0 -2
  2. package/dist/Taskforce.module.css +603 -107
  3. package/dist/TaskforceCore.js +216 -43
  4. package/dist/TaskforceCore.test.js +611 -28
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +46 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
  16. package/dist/components/activity/EntityActivityTimeline.js +81 -0
  17. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  18. package/dist/components/context/ContextAttachmentManager.js +561 -0
  19. package/dist/components/features/AgentsModule.d.ts +14 -1
  20. package/dist/components/features/AgentsModule.js +366 -18
  21. package/dist/components/features/AgentsModule.test.js +507 -8
  22. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
  23. package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
  24. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
  25. package/dist/components/features/DocumentIndex.d.ts +2 -2
  26. package/dist/components/features/DocumentIndex.js +3 -4
  27. package/dist/components/features/DocumentViewer.d.ts +7 -1
  28. package/dist/components/features/DocumentViewer.js +62 -4
  29. package/dist/components/features/DocumentWorkspace.d.ts +10 -2
  30. package/dist/components/features/DocumentWorkspace.js +15 -4
  31. package/dist/components/features/DocumentWorkspace.test.js +51 -1
  32. package/dist/components/features/TaskSettings.d.ts +2 -0
  33. package/dist/components/features/TaskSettings.js +83 -78
  34. package/dist/components/features/TaskSettings.test.js +171 -82
  35. package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
  36. package/dist/components/task/TaskActionHeader.js +11 -5
  37. package/dist/components/task/TaskActionHeader.test.js +10 -0
  38. package/dist/components/task/TaskCard.js +24 -29
  39. package/dist/components/task/TaskCard.test.js +38 -3
  40. package/dist/components/task/TaskContextUpload.js +4 -526
  41. package/dist/components/task/TaskContextUpload.test.js +3 -3
  42. package/dist/components/task/TaskForm.js +61 -116
  43. package/dist/components/task/TaskForm.test.js +110 -8
  44. package/dist/components/task/TaskKanban.d.ts +2 -1
  45. package/dist/components/task/TaskKanban.js +94 -21
  46. package/dist/components/task/TaskKanban.test.js +36 -0
  47. package/dist/components/task/TaskList.js +5 -1
  48. package/dist/components/task/TaskList.test.js +4 -0
  49. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  50. package/dist/components/ui/EditableAvatarButton.js +18 -0
  51. package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
  52. package/dist/components/ui/HierarchyActionBadge.js +5 -0
  53. package/dist/components/views/AppShellHeader.d.ts +3 -1
  54. package/dist/components/views/AppShellHeader.js +27 -11
  55. package/dist/components/views/AppShellHeader.test.js +18 -1
  56. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  57. package/dist/components/views/PlanComparisonPage.js +78 -14
  58. package/dist/components/views/PlanComparisonPage.test.js +257 -0
  59. package/dist/components/views/PlansPage.js +127 -36
  60. package/dist/components/views/PlansPage.test.js +294 -12
  61. package/dist/components/views/StandaloneLayout.js +529 -592
  62. package/dist/components/views/WidgetView.js +10 -8
  63. package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
  64. package/dist/components/views/panels/PlanningDrawer.js +270 -55
  65. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  66. package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
  67. package/dist/components/views/planningScope.d.ts +20 -0
  68. package/dist/components/views/planningScope.js +25 -0
  69. package/dist/components/views/planningScope.test.d.ts +1 -0
  70. package/dist/components/views/planningScope.test.js +60 -0
  71. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
  72. package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
  73. package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
  74. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  75. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  76. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  77. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  78. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  79. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  80. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  81. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  82. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  83. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  84. package/dist/config/envSchema.js +1 -0
  85. package/dist/core/AiProfileService.d.ts +46 -2
  86. package/dist/core/AiProfileService.js +1073 -82
  87. package/dist/core/AiProfileService.test.js +19 -1
  88. package/dist/core/AiProfiles.test.js +1249 -44
  89. package/dist/core/AttachmentLinkService.d.ts +3 -0
  90. package/dist/core/AttachmentLinkService.js +110 -23
  91. package/dist/core/AuthIdentityService.d.ts +107 -0
  92. package/dist/core/AuthIdentityService.js +284 -0
  93. package/dist/core/AuthTokenService.d.ts +4 -0
  94. package/dist/core/AuthTokenService.js +34 -6
  95. package/dist/core/AuthTokenService.test.js +3 -3
  96. package/dist/core/EntitlementsPolicy.test.js +2 -2
  97. package/dist/core/GlobalSettingsService.js +127 -6
  98. package/dist/core/McpTokenService.d.ts +12 -0
  99. package/dist/core/McpTokenService.js +44 -1
  100. package/dist/core/PlanEntitlementService.d.ts +23 -2
  101. package/dist/core/PlanEntitlementService.js +343 -57
  102. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  103. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  104. package/dist/core/PlanVersionPolicy.test.js +35 -2
  105. package/dist/core/PlanningEntities.test.js +418 -4
  106. package/dist/core/SignupMonetizationSettings.test.js +199 -27
  107. package/dist/core/SyncReconciliationService.js +2 -65
  108. package/dist/core/SystemAdmin.test.js +42 -42
  109. package/dist/core/TaskActivityService.d.ts +28 -1
  110. package/dist/core/TaskActivityService.js +227 -46
  111. package/dist/core/TaskActivitySync.test.d.ts +1 -0
  112. package/dist/core/TaskActivitySync.test.js +90 -0
  113. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  114. package/dist/core/TaskAuditTimeline.test.js +96 -0
  115. package/dist/core/Taskforce.d.ts +415 -40
  116. package/dist/core/Taskforce.ids.test.js +58 -0
  117. package/dist/core/Taskforce.js +1543 -266
  118. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  119. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  120. package/dist/core/Taskforce.mcpAuth.test.js +109 -0
  121. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  122. package/dist/core/WorkspaceLifecycleService.js +0 -5
  123. package/dist/core/WorkspacePermissions.test.js +25 -1
  124. package/dist/core/WorkspacePlanMode.test.js +117 -16
  125. package/dist/core/shared.d.ts +1 -1
  126. package/dist/core/shared.js +5 -1
  127. package/dist/core/types.d.ts +75 -2
  128. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
  129. package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
  130. package/dist/hooks/bootstrapTimeouts.js +8 -0
  131. package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
  132. package/dist/hooks/bootstrapTimeouts.test.js +12 -0
  133. package/dist/hooks/sync/bootstrap.js +2 -0
  134. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  135. package/dist/hooks/sync/controlPlane.js +78 -0
  136. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  137. package/dist/hooks/sync/controlPlane.test.js +121 -0
  138. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  139. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  140. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  141. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  142. package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
  143. package/dist/hooks/sync/orchestratorShared.js +129 -48
  144. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  145. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  146. package/dist/hooks/sync/pullLifecycle.js +24 -0
  147. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  148. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  149. package/dist/hooks/sync/recovery.d.ts +16 -2
  150. package/dist/hooks/sync/recovery.js +179 -53
  151. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  152. package/dist/hooks/sync/recovery.test.js +292 -0
  153. package/dist/hooks/sync/transfers.d.ts +16 -3
  154. package/dist/hooks/sync/transfers.js +210 -66
  155. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  156. package/dist/hooks/sync/transfers.test.js +928 -0
  157. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  158. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  159. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  160. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  161. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  162. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  163. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  164. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  165. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  166. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  167. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  168. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  169. package/dist/hooks/useFilterSort.js +13 -13
  170. package/dist/hooks/useFilterSort.test.js +87 -1
  171. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  172. package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
  173. package/dist/hooks/useSyncOrchestrator.js +409 -183
  174. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
  175. package/dist/hooks/useTaskData.js +8 -3
  176. package/dist/hooks/useTaskData.test.js +45 -0
  177. package/dist/hooks/useTaskforce.d.ts +145 -52
  178. package/dist/hooks/useTaskforce.js +592 -253
  179. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  180. package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
  181. package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
  182. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  183. package/dist/hooks/useWorkspaceSyncController.js +13 -2
  184. package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
  185. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  186. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
  187. package/dist/localization/locales/en-US.d.ts +0 -1
  188. package/dist/localization/locales/en-US.js +0 -1
  189. package/dist/localization/locales/es-419.js +0 -1
  190. package/dist/localization/locales/pt-BR.js +0 -1
  191. package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
  192. package/dist/mcp/canonicalAssetHelpers.js +18 -10
  193. package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
  194. package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
  195. package/dist/mcp/clientIntegrations.d.ts +1 -0
  196. package/dist/mcp/clientIntegrations.js +25 -0
  197. package/dist/mcp/clientIntegrations.test.js +14 -3
  198. package/dist/mcp/clientProfileDefaults.js +3 -3
  199. package/dist/mcp/collaborationRegistrar.js +7 -7
  200. package/dist/mcp/documentAssetRegistrar.js +116 -10
  201. package/dist/mcp/runtime.d.ts +3 -0
  202. package/dist/mcp/runtime.js +1099 -185
  203. package/dist/mcp/runtime.test.js +1491 -140
  204. package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
  205. package/dist/mcp/taskPlanningRegistrar.js +48 -0
  206. package/dist/mcp/toolRegistry.d.ts +56 -0
  207. package/dist/mcp/toolRegistry.js +8 -0
  208. package/dist/mcp/toolRegistry.test.js +4 -0
  209. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  210. package/dist/migrations/taskSchemaMigrations.js +192 -61
  211. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  212. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  213. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  214. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  215. package/dist/resources/templates/workflows/plan.yaml +1 -1
  216. package/dist/resources/templates/workflows/review.yaml +2 -2
  217. package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
  218. package/dist/server/aiProfileAvatarAssets.js +319 -0
  219. package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
  220. package/dist/server/aiProfileAvatarAssets.test.js +213 -0
  221. package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
  222. package/dist/server/auth/providers/apple.d.ts +33 -0
  223. package/dist/server/auth/providers/apple.js +82 -0
  224. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  225. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  226. package/dist/server/auth/providers/github.d.ts +26 -0
  227. package/dist/server/auth/providers/github.js +86 -0
  228. package/dist/server/auth/providers/google.d.ts +21 -0
  229. package/dist/server/auth/providers/google.js +56 -0
  230. package/dist/server/auth/providers/types.d.ts +21 -0
  231. package/dist/server/auth/providers/types.js +1 -0
  232. package/dist/server/auth.d.ts +2 -0
  233. package/dist/server/auth.js +6 -3
  234. package/dist/server/documentReviewRoutes.test.js +36 -3
  235. package/dist/server/index.cookieProxy.test.js +1 -0
  236. package/dist/server/index.d.ts +12 -0
  237. package/dist/server/index.js +124 -9
  238. package/dist/server/index.rateLimit.test.js +3 -0
  239. package/dist/server/index.test.js +111 -3
  240. package/dist/server/routes/admin.d.ts +3 -0
  241. package/dist/server/routes/admin.js +459 -28
  242. package/dist/server/routes/annotatedAttachments.js +51 -0
  243. package/dist/server/routes/auth.d.ts +26 -2
  244. package/dist/server/routes/auth.js +1170 -71
  245. package/dist/server/routes/authSupport.d.ts +5 -1
  246. package/dist/server/routes/authSupport.js +13 -2
  247. package/dist/server/routes/billing.js +372 -35
  248. package/dist/server/routes/billing.test.js +595 -12
  249. package/dist/server/routes/documents.d.ts +1 -0
  250. package/dist/server/routes/documents.js +182 -70
  251. package/dist/server/routes/shared.d.ts +28 -2
  252. package/dist/server/routes/shared.js +69 -14
  253. package/dist/server/routes/sync.integration.test.js +658 -39
  254. package/dist/server/routes/sync.js +74 -608
  255. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  256. package/dist/server/routes/syncAuxRoutes.js +91 -0
  257. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  258. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  259. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  260. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  261. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  262. package/dist/server/routes/syncPushRoutes.js +212 -0
  263. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  264. package/dist/server/routes/syncRouteGuards.js +67 -0
  265. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  266. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  267. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  268. package/dist/server/routes/syncRouteTypes.js +1 -0
  269. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  270. package/dist/server/routes/syncSnapshotRoutes.js +182 -0
  271. package/dist/server/routes/tasks.js +55 -10
  272. package/dist/server/routes/workspaces.js +36 -5
  273. package/dist/server/routes.js +147 -11
  274. package/dist/server/routes.test.js +2704 -183
  275. package/dist/services/workflowExportSnapshots.test.js +2 -0
  276. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  277. package/dist/shared/aiProfileSeatScope.js +21 -0
  278. package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
  279. package/dist/shared/aiProfileSurfaceType.js +10 -8
  280. package/dist/shared/passwordPolicy.d.ts +13 -0
  281. package/dist/shared/passwordPolicy.js +84 -0
  282. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  283. package/dist/shared/passwordPolicy.test.js +34 -0
  284. package/dist/storage/objectStorage.d.ts +1 -0
  285. package/dist/storage/objectStorage.js +2 -1
  286. package/dist/storage/objectStorageClient.d.ts +1 -0
  287. package/dist/storage/objectStorageClient.js +41 -8
  288. package/dist/storage/objectStorageClient.test.js +26 -1
  289. package/dist/storage/objectStorageConfig.js +3 -1
  290. package/dist/storage/objectStorageConfig.test.js +13 -1
  291. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  292. package/dist/storage/workspaceAssetStore.js +132 -44
  293. package/dist/storage/workspaceAssetStore.test.js +93 -6
  294. package/dist/styles/fonts.css +70 -0
  295. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  296. package/dist/sync/collaborationSyncPayload.js +19 -11
  297. package/dist/sync/collaborationSyncPayload.test.js +14 -1
  298. package/dist/sync/collaborationSyncState.d.ts +3 -3
  299. package/dist/sync/collaborationSyncState.js +19 -12
  300. package/dist/sync/contentSyncPayload.d.ts +5 -1
  301. package/dist/sync/contentSyncPayload.js +9 -0
  302. package/dist/sync/contentSyncPayload.test.js +39 -0
  303. package/dist/sync/contentSyncState.d.ts +9 -9
  304. package/dist/sync/contentSyncState.js +248 -107
  305. package/dist/sync/planningSyncPayload.js +5 -0
  306. package/dist/sync/planningSyncPayload.test.js +24 -0
  307. package/dist/sync/syncApplyHandlers.d.ts +11 -4
  308. package/dist/sync/syncApplyHandlers.js +115 -42
  309. package/dist/sync/syncApplyHandlers.test.js +251 -4
  310. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  311. package/dist/sync/syncFieldSemantics.js +55 -0
  312. package/dist/sync/syncResourceAdapters.d.ts +46 -0
  313. package/dist/sync/syncResourceAdapters.js +79 -0
  314. package/dist/sync/syncService.d.ts +6 -0
  315. package/dist/sync/syncService.js +65 -1
  316. package/dist/sync/syncService.test.js +96 -3
  317. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  318. package/dist/sync/taskSyncChangeKey.js +143 -0
  319. package/dist/sync/taskSyncPayload.js +3 -8
  320. package/dist/sync/workspacePullFeed.d.ts +4 -0
  321. package/dist/sync/workspacePullFeed.js +132 -72
  322. package/dist/sync/workspacePullFeed.test.js +92 -0
  323. package/dist/sync/workspaceRepair.js +5 -2
  324. package/dist/sync/workspaceSyncModel.d.ts +73 -6
  325. package/dist/sync/workspaceSyncModel.js +342 -73
  326. package/dist/sync/workspaceSyncModel.test.js +559 -14
  327. package/dist/sync/workspaceSyncState.d.ts +17 -0
  328. package/dist/sync/workspaceSyncState.js +2 -1
  329. package/dist/sync/workspaceSyncSurface.js +3 -8
  330. package/dist/types.d.ts +50 -2
  331. package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
  332. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
  333. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
  334. package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
  335. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  336. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  337. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  338. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  339. package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
  340. package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
  341. package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
  342. package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
  343. package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
  344. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  345. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  346. package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
  347. package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
  348. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  349. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  350. package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
  351. package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
  352. package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
  353. package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
  354. package/dist/ui/assets/index-607WPo_X.js +4 -0
  355. package/dist/ui/assets/index-CYyodXsg.css +1 -0
  356. package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
  357. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  358. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  359. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  360. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  361. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  362. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  363. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  364. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  365. package/dist/ui/fonts/Noir_medium.otf +0 -0
  366. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  367. package/dist/ui/fonts/Noir_regular.otf +0 -0
  368. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  369. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  370. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  371. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  372. package/dist/ui/index.html +3 -3
  373. package/dist/ui/product/agent manager.png +0 -0
  374. package/dist/ui/product/agent_manager_02.png +0 -0
  375. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  376. package/dist/utils/aiProfileEvents.d.ts +7 -0
  377. package/dist/utils/aiProfileEvents.js +6 -0
  378. package/dist/utils/assignees.d.ts +8 -0
  379. package/dist/utils/assignees.js +10 -1
  380. package/dist/utils/assignees.test.d.ts +1 -0
  381. package/dist/utils/assignees.test.js +25 -0
  382. package/dist/utils/avatarDisplay.d.ts +1 -0
  383. package/dist/utils/avatarDisplay.js +15 -0
  384. package/dist/utils/avatarUpload.d.ts +27 -0
  385. package/dist/utils/avatarUpload.js +132 -0
  386. package/dist/utils/avatarUpload.test.d.ts +1 -0
  387. package/dist/utils/avatarUpload.test.js +40 -0
  388. package/dist/utils/bootstrapTrace.d.ts +7 -0
  389. package/dist/utils/bootstrapTrace.js +29 -0
  390. package/dist/utils/commercialLifecyclePresentation.js +3 -0
  391. package/dist/utils/contextAssetEvents.d.ts +2 -0
  392. package/dist/utils/contextFiles.d.ts +3 -1
  393. package/dist/utils/contextFiles.js +2 -1
  394. package/dist/utils/syncEventDetails.d.ts +3 -0
  395. package/dist/utils/syncEventDetails.js +64 -0
  396. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  397. package/dist/utils/syncEventDetails.test.js +23 -0
  398. package/dist/utils/syncEventPresentation.d.ts +15 -0
  399. package/dist/utils/syncEventPresentation.js +129 -0
  400. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  401. package/dist/utils/syncEventPresentation.test.js +64 -0
  402. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  403. package/dist/utils/syncStatusPresentation.js +217 -0
  404. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  405. package/dist/utils/syncStatusPresentation.test.js +164 -0
  406. package/dist/utils/taskActivity.d.ts +9 -1
  407. package/dist/utils/taskActivity.js +290 -22
  408. package/dist/utils/taskActivity.test.js +141 -8
  409. package/dist/utils/taskSearch.d.ts +22 -0
  410. package/dist/utils/taskSearch.js +87 -0
  411. package/dist/utils/taskSearch.test.d.ts +1 -0
  412. package/dist/utils/taskSearch.test.js +69 -0
  413. package/dist/utils/taskUtils.js +10 -3
  414. package/dist/utils/taskUtils.test.d.ts +1 -0
  415. package/dist/utils/taskUtils.test.js +19 -0
  416. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  417. package/dist/utils/workspaceSyncPresentation.js +68 -2
  418. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  419. package/package.json +3 -2
  420. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  421. package/scripts/run-e2e-realtime.sh +17 -3
  422. package/scripts/run-smoke.sh +17 -5
  423. package/scripts/run-soak.sh +17 -5
  424. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  425. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  426. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  427. package/src/resources/templates/workflows/plan.yaml +1 -1
  428. package/src/resources/templates/workflows/review.yaml +2 -2
  429. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
  430. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
  431. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
  432. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
  433. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
  434. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  435. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
  436. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  437. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
  438. package/dist/ui/assets/index-C2-OXZV7.css +0 -1
  439. package/dist/ui/assets/index-DcSI5F86.js +0 -6
  440. package/scripts/migrate-planning-model.ts +0 -233
@@ -6,7 +6,7 @@ export type TaskAttachmentRecord = {
6
6
  displayName?: string;
7
7
  originalFilename?: string;
8
8
  timestamp?: string;
9
- assetId?: string;
9
+ assetId?: string | null;
10
10
  referenceNumber?: number | null;
11
11
  referenceLabel?: string | null;
12
12
  taskId?: string | null;
@@ -87,6 +87,18 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
87
87
  description: stringProperty('Optional initiative description.'),
88
88
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
89
89
  order: numberProperty('Optional sort order among initiatives.'),
90
+ attachments: arrayProperty('Optional attachment descriptors to store on the initiative. Prefer save_initiative_attachment for generated content or files.', {
91
+ type: 'object',
92
+ properties: {
93
+ path: { type: 'string' },
94
+ fsPath: { type: 'string' },
95
+ caption: { type: 'string' },
96
+ displayName: { type: 'string' },
97
+ originalFilename: { type: 'string' },
98
+ assetId: { type: 'string' },
99
+ },
100
+ required: ['path'],
101
+ }),
90
102
  },
91
103
  required: ['title'],
92
104
  },
@@ -100,6 +112,18 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
100
112
  description: stringProperty('Updated initiative description.'),
101
113
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
102
114
  order: numberProperty('Optional sort order among initiatives.'),
115
+ attachments: arrayProperty('Replacement attachment descriptors for the initiative. Prefer save_initiative_attachment and delete_initiative_attachment for generated content or files.', {
116
+ type: 'object',
117
+ properties: {
118
+ path: { type: 'string' },
119
+ fsPath: { type: 'string' },
120
+ caption: { type: 'string' },
121
+ displayName: { type: 'string' },
122
+ originalFilename: { type: 'string' },
123
+ assetId: { type: 'string' },
124
+ },
125
+ required: ['path'],
126
+ }),
103
127
  },
104
128
  required: ['id'],
105
129
  },
@@ -144,6 +168,18 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
144
168
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
145
169
  initiativeId: stringProperty('Optional initiative ID or initiative reference such as IN-123.'),
146
170
  order: numberProperty('Optional sort order among workstreams.'),
171
+ attachments: arrayProperty('Optional attachment descriptors to store on the workstream. Prefer save_workstream_attachment for generated content or files.', {
172
+ type: 'object',
173
+ properties: {
174
+ path: { type: 'string' },
175
+ fsPath: { type: 'string' },
176
+ caption: { type: 'string' },
177
+ displayName: { type: 'string' },
178
+ originalFilename: { type: 'string' },
179
+ assetId: { type: 'string' },
180
+ },
181
+ required: ['path'],
182
+ }),
147
183
  },
148
184
  required: ['title'],
149
185
  },
@@ -158,6 +194,18 @@ export function registerTaskPlanningTools(registerTool, executeTool) {
158
194
  ownerId: stringProperty(`${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.`),
159
195
  initiativeId: stringProperty('Optional initiative ID or initiative reference such as IN-123. Pass an empty string to unlink.'),
160
196
  order: numberProperty('Optional sort order among workstreams.'),
197
+ attachments: arrayProperty('Replacement attachment descriptors for the workstream. Prefer save_workstream_attachment and delete_workstream_attachment for generated content or files.', {
198
+ type: 'object',
199
+ properties: {
200
+ path: { type: 'string' },
201
+ fsPath: { type: 'string' },
202
+ caption: { type: 'string' },
203
+ displayName: { type: 'string' },
204
+ originalFilename: { type: 'string' },
205
+ assetId: { type: 'string' },
206
+ },
207
+ required: ['path'],
208
+ }),
161
209
  },
162
210
  required: ['id'],
163
211
  },
@@ -185,6 +185,62 @@ export declare const MCP_TOOL_REGISTRY: Readonly<{
185
185
  };
186
186
  readonly mutating: false;
187
187
  };
188
+ readonly get_workstream_attachments: {
189
+ readonly permission: {
190
+ readonly kind: "scope";
191
+ readonly scope: "tasks:read";
192
+ };
193
+ readonly mutating: false;
194
+ };
195
+ readonly read_workstream_attachment: {
196
+ readonly permission: {
197
+ readonly kind: "scope";
198
+ readonly scope: "tasks:read";
199
+ };
200
+ readonly mutating: false;
201
+ };
202
+ readonly save_workstream_attachment: {
203
+ readonly permission: {
204
+ readonly kind: "scope";
205
+ readonly scope: "tasks:write";
206
+ };
207
+ readonly mutating: true;
208
+ };
209
+ readonly delete_workstream_attachment: {
210
+ readonly permission: {
211
+ readonly kind: "scope";
212
+ readonly scope: "tasks:write";
213
+ };
214
+ readonly mutating: true;
215
+ };
216
+ readonly get_initiative_attachments: {
217
+ readonly permission: {
218
+ readonly kind: "scope";
219
+ readonly scope: "tasks:read";
220
+ };
221
+ readonly mutating: false;
222
+ };
223
+ readonly read_initiative_attachment: {
224
+ readonly permission: {
225
+ readonly kind: "scope";
226
+ readonly scope: "tasks:read";
227
+ };
228
+ readonly mutating: false;
229
+ };
230
+ readonly save_initiative_attachment: {
231
+ readonly permission: {
232
+ readonly kind: "scope";
233
+ readonly scope: "tasks:write";
234
+ };
235
+ readonly mutating: true;
236
+ };
237
+ readonly delete_initiative_attachment: {
238
+ readonly permission: {
239
+ readonly kind: "scope";
240
+ readonly scope: "tasks:write";
241
+ };
242
+ readonly mutating: true;
243
+ };
188
244
  readonly search_images: {
189
245
  readonly permission: {
190
246
  readonly kind: "scope";
@@ -26,6 +26,14 @@ export const MCP_TOOL_REGISTRY = Object.freeze({
26
26
  replace_task_checklist: { permission: { kind: 'scope', scope: 'tasks:write' }, mutating: true },
27
27
  get_task_attachments: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
28
28
  read_task_attachment: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
29
+ get_workstream_attachments: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
30
+ read_workstream_attachment: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
31
+ save_workstream_attachment: { permission: { kind: 'scope', scope: 'tasks:write' }, mutating: true },
32
+ delete_workstream_attachment: { permission: { kind: 'scope', scope: 'tasks:write' }, mutating: true },
33
+ get_initiative_attachments: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
34
+ read_initiative_attachment: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
35
+ save_initiative_attachment: { permission: { kind: 'scope', scope: 'tasks:write' }, mutating: true },
36
+ delete_initiative_attachment: { permission: { kind: 'scope', scope: 'tasks:write' }, mutating: true },
29
37
  search_images: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
30
38
  get_image: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
31
39
  search_documents: { permission: { kind: 'scope', scope: 'tasks:read' }, mutating: false },
@@ -11,6 +11,8 @@ describe('MCP tool registry', () => {
11
11
  expect(MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS.search_documents).toBe('tasks:read');
12
12
  expect(MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS.read_task_attachment).toBe('tasks:read');
13
13
  expect(MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS.get_task_attachments).toBe('tasks:read');
14
+ expect(MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS.read_workstream_attachment).toBe('tasks:read');
15
+ expect(MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS.get_initiative_attachments).toBe('tasks:read');
14
16
  expect(MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS.export_resources).toBeUndefined();
15
17
  });
16
18
  it('derives mutating tool names from the shared registry', () => {
@@ -20,6 +22,8 @@ describe('MCP tool registry', () => {
20
22
  expect(MCP_WRITE_TOOL_NAMES).toEqual(expected);
21
23
  expect(MCP_WRITE_TOOL_NAMES.has('read_task_attachment')).toBe(false);
22
24
  expect(MCP_WRITE_TOOL_NAMES.has('save_task_attachment')).toBe(true);
25
+ expect(MCP_WRITE_TOOL_NAMES.has('save_workstream_attachment')).toBe(true);
26
+ expect(MCP_WRITE_TOOL_NAMES.has('delete_initiative_attachment')).toBe(true);
23
27
  expect(MCP_WRITE_TOOL_NAMES.has('finish_task')).toBe(true);
24
28
  expect(MCP_WRITE_TOOL_NAMES.has('review_document')).toBe(true);
25
29
  });
@@ -1,6 +1,5 @@
1
1
  import type { DatabaseAdapter } from '../storage/databaseAdapter.js';
2
2
  export declare function ensureTenantSchema(db: DatabaseAdapter): void;
3
- export declare function ensureParentTaskSchema(db: DatabaseAdapter): void;
4
3
  export declare function ensureScheduleTaskSchema(db: DatabaseAdapter): void;
5
4
  export declare function ensureAssigneeTaskSchema(db: DatabaseAdapter): void;
6
5
  export declare function ensureTaskReferenceSchema(db: DatabaseAdapter): void;
@@ -14,3 +13,4 @@ export declare function ensureSyncEventsSchema(db: DatabaseAdapter): void;
14
13
  export declare function ensureWorkspaceDocumentsSchema(db: DatabaseAdapter): void;
15
14
  export declare function ensureAnnotatedAttachmentSessionsSchema(db: DatabaseAdapter): void;
16
15
  export declare function ensureDocumentReviewSessionsSchema(db: DatabaseAdapter): void;
16
+ export declare function ensureAuthIdentitySchema(db: DatabaseAdapter): void;
@@ -34,58 +34,6 @@ export function ensureTenantSchema(db) {
34
34
  CREATE INDEX IF NOT EXISTS idx_comments_tenant_task ON comments(tenant_id, task_id);
35
35
  `);
36
36
  }
37
- export function ensureParentTaskSchema(db) {
38
- const columns = db.prepare(`PRAGMA table_info(tasks)`).all();
39
- const hasParentColumn = columns.some((c) => c.name === 'parent_task_id');
40
- const hasChildDisplayOrderColumn = columns.some((c) => c.name === 'child_display_order');
41
- if (!hasParentColumn) {
42
- db.exec(`ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`);
43
- }
44
- if (!hasChildDisplayOrderColumn) {
45
- db.exec(`ALTER TABLE tasks ADD COLUMN child_display_order INTEGER`);
46
- }
47
- db.exec(`
48
- CREATE INDEX IF NOT EXISTS idx_tasks_parent_task_id ON tasks(parent_task_id);
49
- CREATE INDEX IF NOT EXISTS idx_tasks_parent_child_order ON tasks(parent_task_id, child_display_order);
50
- `);
51
- // SQLite-only runtime guard triggers. Postgres path enforces constraints in core logic.
52
- if (db.provider === 'sqlite') {
53
- db.exec(`
54
- CREATE TRIGGER IF NOT EXISTS trg_tasks_parent_guard_insert
55
- BEFORE INSERT ON tasks
56
- FOR EACH ROW
57
- WHEN NEW.parent_task_id IS NOT NULL AND TRIM(NEW.parent_task_id) <> ''
58
- BEGIN
59
- SELECT CASE
60
- WHEN NEW.parent_task_id = NEW.id THEN RAISE(ABORT, 'Task cannot parent itself')
61
- WHEN (SELECT id FROM tasks WHERE id = NEW.parent_task_id) IS NULL THEN RAISE(ABORT, 'Parent task not found')
62
- END;
63
- END;
64
- `);
65
- db.exec(`
66
- CREATE TRIGGER IF NOT EXISTS trg_tasks_parent_guard_update
67
- BEFORE UPDATE OF parent_task_id ON tasks
68
- FOR EACH ROW
69
- WHEN NEW.parent_task_id IS NOT NULL AND TRIM(NEW.parent_task_id) <> ''
70
- BEGIN
71
- SELECT CASE
72
- WHEN NEW.parent_task_id = NEW.id THEN RAISE(ABORT, 'Task cannot parent itself')
73
- WHEN (SELECT id FROM tasks WHERE id = NEW.parent_task_id) IS NULL THEN RAISE(ABORT, 'Parent task not found')
74
- END;
75
- END;
76
- `);
77
- // Block deletion of parent tasks while children still point to them.
78
- db.exec(`
79
- CREATE TRIGGER IF NOT EXISTS trg_tasks_block_delete_with_children
80
- BEFORE DELETE ON tasks
81
- FOR EACH ROW
82
- WHEN EXISTS (SELECT 1 FROM tasks WHERE parent_task_id = OLD.id)
83
- BEGIN
84
- SELECT RAISE(ABORT, 'Cannot delete parent task with children');
85
- END;
86
- `);
87
- }
88
- }
89
37
  export function ensureScheduleTaskSchema(db) {
90
38
  const columns = db.prepare(`PRAGMA table_info(tasks)`).all();
91
39
  const hasScheduledDateColumn = columns.some((c) => c.name === 'scheduled_date');
@@ -226,9 +174,6 @@ export function ensureWorkspaceSchema(db) {
226
174
  email TEXT NOT NULL,
227
175
  display_name TEXT,
228
176
  avatar_url TEXT,
229
- auth_provider TEXT,
230
- external_auth_id TEXT,
231
- password_hash TEXT,
232
177
  email_verified_at TEXT,
233
178
  beta_access BOOLEAN NOT NULL DEFAULT TRUE,
234
179
  is_disabled BOOLEAN NOT NULL DEFAULT FALSE,
@@ -253,6 +198,25 @@ export function ensureWorkspaceSchema(db) {
253
198
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
254
199
  );
255
200
 
201
+ CREATE TABLE IF NOT EXISTS task_attachment_upload_drafts (
202
+ draft_id TEXT PRIMARY KEY,
203
+ tenant_id TEXT NOT NULL DEFAULT 'default',
204
+ workspace_id TEXT NOT NULL,
205
+ task_id TEXT NOT NULL,
206
+ actor_ref TEXT NOT NULL,
207
+ storage_key TEXT NOT NULL,
208
+ mime_type TEXT NOT NULL,
209
+ original_filename TEXT NOT NULL,
210
+ size_bytes INTEGER NOT NULL DEFAULT 0,
211
+ storage_provider TEXT NOT NULL DEFAULT 'local',
212
+ consumed_at TEXT,
213
+ discarded_at TEXT,
214
+ created_at TEXT NOT NULL,
215
+ updated_at TEXT NOT NULL,
216
+ FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
217
+ FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
218
+ );
219
+
256
220
  CREATE TABLE IF NOT EXISTS auth_tokens (
257
221
  id TEXT PRIMARY KEY,
258
222
  tenant_id TEXT NOT NULL DEFAULT 'default',
@@ -319,9 +283,6 @@ export function ensureWorkspaceSchema(db) {
319
283
  const postgresUserRepairs = [
320
284
  `ALTER TABLE users ADD COLUMN IF NOT EXISTS display_name TEXT`,
321
285
  `ALTER TABLE users ADD COLUMN IF NOT EXISTS avatar_url TEXT`,
322
- `ALTER TABLE users ADD COLUMN IF NOT EXISTS auth_provider TEXT`,
323
- `ALTER TABLE users ADD COLUMN IF NOT EXISTS external_auth_id TEXT`,
324
- `ALTER TABLE users ADD COLUMN IF NOT EXISTS password_hash TEXT`,
325
286
  `ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified_at TEXT`,
326
287
  `ALTER TABLE users ADD COLUMN IF NOT EXISTS beta_access BOOLEAN NOT NULL DEFAULT TRUE`,
327
288
  `ALTER TABLE users ADD COLUMN IF NOT EXISTS is_disabled BOOLEAN NOT NULL DEFAULT FALSE`,
@@ -357,9 +318,6 @@ export function ensureWorkspaceSchema(db) {
357
318
  const sqliteUserRepairs = [
358
319
  { name: 'display_name', sql: `ALTER TABLE users ADD COLUMN display_name TEXT` },
359
320
  { name: 'avatar_url', sql: `ALTER TABLE users ADD COLUMN avatar_url TEXT` },
360
- { name: 'auth_provider', sql: `ALTER TABLE users ADD COLUMN auth_provider TEXT` },
361
- { name: 'external_auth_id', sql: `ALTER TABLE users ADD COLUMN external_auth_id TEXT` },
362
- { name: 'password_hash', sql: `ALTER TABLE users ADD COLUMN password_hash TEXT` },
363
321
  { name: 'email_verified_at', sql: `ALTER TABLE users ADD COLUMN email_verified_at TEXT` },
364
322
  { name: 'beta_access', sql: `ALTER TABLE users ADD COLUMN beta_access BOOLEAN NOT NULL DEFAULT TRUE` },
365
323
  { name: 'is_disabled', sql: `ALTER TABLE users ADD COLUMN is_disabled BOOLEAN NOT NULL DEFAULT FALSE` },
@@ -449,6 +407,8 @@ export function ensureWorkspaceSchema(db) {
449
407
  CREATE INDEX IF NOT EXISTS idx_auth_tokens_user_purpose ON auth_tokens(user_id, purpose);
450
408
  CREATE INDEX IF NOT EXISTS idx_auth_tokens_workspace_purpose ON auth_tokens(workspace_id, purpose);
451
409
  CREATE INDEX IF NOT EXISTS idx_auth_tokens_expires ON auth_tokens(expires_at);
410
+ CREATE INDEX IF NOT EXISTS idx_task_attachment_upload_drafts_workspace_task ON task_attachment_upload_drafts(workspace_id, task_id);
411
+ CREATE INDEX IF NOT EXISTS idx_task_attachment_upload_drafts_actor_created ON task_attachment_upload_drafts(actor_ref, created_at);
452
412
  CREATE UNIQUE INDEX IF NOT EXISTS idx_mcp_access_tokens_prefix ON mcp_access_tokens(token_prefix);
453
413
  CREATE INDEX IF NOT EXISTS idx_mcp_access_tokens_workspace_user ON mcp_access_tokens(workspace_id, user_id);
454
414
  CREATE INDEX IF NOT EXISTS idx_mcp_access_tokens_status ON mcp_access_tokens(status);
@@ -697,6 +657,7 @@ export function ensureEntitlementsSchema(db) {
697
657
  plan_id TEXT PRIMARY KEY,
698
658
  tenant_id TEXT NOT NULL DEFAULT 'default',
699
659
  display_name TEXT NOT NULL,
660
+ description TEXT,
700
661
  status TEXT NOT NULL DEFAULT 'active',
701
662
  created_at TEXT NOT NULL,
702
663
  updated_at TEXT NOT NULL
@@ -727,6 +688,17 @@ export function ensureEntitlementsSchema(db) {
727
688
  FOREIGN KEY (plan_version_id) REFERENCES plan_versions(plan_version_id) ON DELETE CASCADE
728
689
  );
729
690
 
691
+ CREATE TABLE IF NOT EXISTS plan_feature_catalog_overrides (
692
+ tenant_id TEXT NOT NULL DEFAULT 'default',
693
+ feature_key TEXT NOT NULL,
694
+ public_label TEXT,
695
+ public_description TEXT,
696
+ public_display_order INTEGER,
697
+ created_at TEXT NOT NULL,
698
+ updated_at TEXT NOT NULL,
699
+ PRIMARY KEY (tenant_id, feature_key)
700
+ );
701
+
730
702
  CREATE TABLE IF NOT EXISTS account_entitlements (
731
703
  account_id TEXT PRIMARY KEY,
732
704
  tenant_id TEXT NOT NULL DEFAULT 'default',
@@ -763,6 +735,8 @@ export function ensureEntitlementsSchema(db) {
763
735
  ON plan_versions(tenant_id, plan_id, is_default);
764
736
  CREATE INDEX IF NOT EXISTS idx_plan_feature_matrix_plan_version
765
737
  ON plan_feature_matrix(tenant_id, plan_version_id);
738
+ CREATE INDEX IF NOT EXISTS idx_plan_feature_catalog_overrides_tenant
739
+ ON plan_feature_catalog_overrides(tenant_id, updated_at);
766
740
  CREATE INDEX IF NOT EXISTS idx_account_entitlements_state
767
741
  ON account_entitlements(tenant_id, entitlement_state);
768
742
  CREATE INDEX IF NOT EXISTS idx_account_entitlements_plan_version
@@ -774,6 +748,15 @@ export function ensureEntitlementsSchema(db) {
774
748
  CREATE INDEX IF NOT EXISTS idx_entitlement_audit_log_actor
775
749
  ON entitlement_audit_log(tenant_id, actor_user_id, created_at);
776
750
  `);
751
+ const planCatalogColumns = db.prepare(`PRAGMA table_info(plan_catalog)`).all();
752
+ const hasDescriptionColumn = planCatalogColumns.some((c) => c.name === 'description');
753
+ if (!hasDescriptionColumn) {
754
+ db.exec(`ALTER TABLE plan_catalog ADD COLUMN description TEXT`);
755
+ }
756
+ const planFeatureCatalogOverrideColumns = db.prepare(`PRAGMA table_info(plan_feature_catalog_overrides)`).all();
757
+ if (!planFeatureCatalogOverrideColumns.some((column) => column.name === 'public_display_order')) {
758
+ db.exec(`ALTER TABLE plan_feature_catalog_overrides ADD COLUMN public_display_order INTEGER`);
759
+ }
777
760
  }
778
761
  export function ensureTaskAssetsSchema(db) {
779
762
  db.exec(`
@@ -853,6 +836,7 @@ export function ensureWorkspaceAssetsSchema(db) {
853
836
  tenant_id TEXT NOT NULL DEFAULT 'default',
854
837
  workspace_id TEXT NOT NULL,
855
838
  asset_id TEXT NOT NULL,
839
+ target_type TEXT NOT NULL DEFAULT 'task',
856
840
  task_id TEXT NOT NULL,
857
841
  role TEXT NOT NULL,
858
842
  display_name TEXT,
@@ -873,6 +857,15 @@ export function ensureWorkspaceAssetsSchema(db) {
873
857
  if (!hasDisplayNameColumn) {
874
858
  db.exec(`ALTER TABLE workspace_asset_links ADD COLUMN display_name TEXT`);
875
859
  }
860
+ const hasTargetTypeColumn = linkColumns.some((c) => c.name === 'target_type');
861
+ if (!hasTargetTypeColumn) {
862
+ db.exec(`ALTER TABLE workspace_asset_links ADD COLUMN target_type TEXT NOT NULL DEFAULT 'task'`);
863
+ db.exec(`UPDATE workspace_asset_links SET target_type = 'task' WHERE target_type IS NULL OR TRIM(target_type) = ''`);
864
+ }
865
+ db.exec(`
866
+ CREATE INDEX IF NOT EXISTS idx_workspace_asset_links_target
867
+ ON workspace_asset_links(tenant_id, workspace_id, target_type, task_id, deleted_at, updated_at)
868
+ `);
876
869
  }
877
870
  export function ensureDocumentReferenceSchema(db) {
878
871
  const columns = db.prepare(`PRAGMA table_info(workspace_assets)`).all();
@@ -1160,3 +1153,141 @@ export function ensureDocumentReviewSessionsSchema(db) {
1160
1153
  }
1161
1154
  }
1162
1155
  }
1156
+ export function ensureAuthIdentitySchema(db) {
1157
+ db.exec(`
1158
+ CREATE TABLE IF NOT EXISTS user_auth_identities (
1159
+ id TEXT PRIMARY KEY,
1160
+ tenant_id TEXT NOT NULL DEFAULT 'default',
1161
+ user_id TEXT NOT NULL,
1162
+ provider TEXT NOT NULL,
1163
+ provider_subject TEXT,
1164
+ provider_email TEXT,
1165
+ provider_email_verified INTEGER,
1166
+ password_hash TEXT,
1167
+ display_name_snapshot TEXT,
1168
+ avatar_url_snapshot TEXT,
1169
+ metadata_json TEXT,
1170
+ created_at TEXT NOT NULL,
1171
+ updated_at TEXT NOT NULL,
1172
+ last_login_at TEXT,
1173
+ linked_at TEXT,
1174
+ disabled_at TEXT,
1175
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
1176
+ );
1177
+
1178
+ CREATE TABLE IF NOT EXISTS auth_oauth_states (
1179
+ state TEXT PRIMARY KEY,
1180
+ tenant_id TEXT NOT NULL DEFAULT 'default',
1181
+ provider TEXT NOT NULL,
1182
+ flow_mode TEXT NOT NULL,
1183
+ user_id TEXT,
1184
+ invite_token TEXT,
1185
+ return_to TEXT,
1186
+ pkce_verifier TEXT,
1187
+ nonce TEXT,
1188
+ expires_at TEXT NOT NULL,
1189
+ consumed_at TEXT,
1190
+ created_at TEXT NOT NULL,
1191
+ created_ip TEXT
1192
+ );
1193
+ `);
1194
+ if (db.provider === 'postgres') {
1195
+ try {
1196
+ db.exec(`
1197
+ ALTER TABLE user_auth_identities
1198
+ ADD CONSTRAINT uq_auth_identity_provider_subject
1199
+ UNIQUE (tenant_id, provider, provider_subject)
1200
+ `);
1201
+ }
1202
+ catch { /* already exists */ }
1203
+ try {
1204
+ db.exec(`
1205
+ ALTER TABLE user_auth_identities
1206
+ ADD CONSTRAINT uq_auth_identity_user_provider
1207
+ UNIQUE (tenant_id, user_id, provider)
1208
+ `);
1209
+ }
1210
+ catch { /* already exists */ }
1211
+ }
1212
+ else {
1213
+ // SQLite: create unique indexes if they don't already exist
1214
+ db.exec(`
1215
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_auth_identity_provider_subject
1216
+ ON user_auth_identities(tenant_id, provider, provider_subject)
1217
+ WHERE provider_subject IS NOT NULL;
1218
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_auth_identity_user_provider
1219
+ ON user_auth_identities(tenant_id, user_id, provider);
1220
+ `);
1221
+ }
1222
+ db.exec(`
1223
+ CREATE INDEX IF NOT EXISTS idx_auth_identities_user
1224
+ ON user_auth_identities(tenant_id, user_id);
1225
+ CREATE INDEX IF NOT EXISTS idx_auth_oauth_states_expires
1226
+ ON auth_oauth_states(expires_at);
1227
+ `);
1228
+ // ── Backfill: migrate any remaining users.password_hash rows into user_auth_identities.
1229
+ // Guarded: wrapped in try/catch — if the legacy column was already dropped (T-837),
1230
+ // the SELECT will throw and we skip cleanly. Idempotent via unique index.
1231
+ try {
1232
+ const now = new Date().toISOString();
1233
+ const usersWithPassword = db.prepare(`
1234
+ SELECT id, tenant_id, password_hash
1235
+ FROM users
1236
+ WHERE password_hash IS NOT NULL
1237
+ AND TRIM(COALESCE(password_hash, '')) != ''
1238
+ `).all();
1239
+ const hasIdentity = db.prepare(`
1240
+ SELECT id FROM user_auth_identities
1241
+ WHERE tenant_id = ? AND user_id = ? AND provider = 'password'
1242
+ LIMIT 1
1243
+ `);
1244
+ const insertIdentity = db.prepare(`
1245
+ INSERT INTO user_auth_identities
1246
+ (id, tenant_id, user_id, provider, password_hash, created_at, updated_at, linked_at)
1247
+ VALUES (?, ?, ?, 'password', ?, ?, ?, ?)
1248
+ `);
1249
+ for (const user of usersWithPassword) {
1250
+ const existing = hasIdentity.get(user.tenant_id, user.id);
1251
+ if (existing?.id)
1252
+ continue;
1253
+ const identityId = `identity-${user.id}-pwd`;
1254
+ try {
1255
+ insertIdentity.run(identityId, user.tenant_id, user.id, user.password_hash, now, now, now);
1256
+ }
1257
+ catch {
1258
+ // Concurrent startup or duplicate — safe to skip.
1259
+ }
1260
+ }
1261
+ }
1262
+ catch {
1263
+ // users.password_hash column already absent — backfill not needed.
1264
+ }
1265
+ // ── Drop legacy auth columns from users (T-837).
1266
+ // Safe to run repeatedly: column-existence checks prevent double-drop errors.
1267
+ if (db.provider === 'postgres') {
1268
+ // PostgreSQL: DROP COLUMN IF EXISTS is a single atomic statement.
1269
+ try {
1270
+ db.exec(`
1271
+ ALTER TABLE users
1272
+ DROP COLUMN IF EXISTS auth_provider,
1273
+ DROP COLUMN IF EXISTS external_auth_id,
1274
+ DROP COLUMN IF EXISTS password_hash
1275
+ `);
1276
+ }
1277
+ catch { /* best-effort — ignore if already absent */ }
1278
+ }
1279
+ else {
1280
+ // SQLite: DROP COLUMN requires 3.35.0+ (2021-03-12).
1281
+ // better-sqlite3 ships its own SQLite which satisfies this requirement.
1282
+ // Guard each drop individually to tolerate partial completion.
1283
+ const currentUserCols = new Set(db.prepare(`PRAGMA table_info(users)`).all().map(c => c.name));
1284
+ for (const col of ['auth_provider', 'external_auth_id', 'password_hash']) {
1285
+ if (currentUserCols.has(col)) {
1286
+ try {
1287
+ db.exec(`ALTER TABLE users DROP COLUMN ${col}`);
1288
+ }
1289
+ catch { /* ignore — concurrent drop or already gone */ }
1290
+ }
1291
+ }
1292
+ }
1293
+ }
@@ -1,4 +1,6 @@
1
1
  import Database from 'better-sqlite3';
2
+ import fs from 'fs';
3
+ import path from 'path';
2
4
  import { afterEach, describe, expect, it } from 'vitest';
3
5
  import { ensureAnnotatedAttachmentSessionsSchema, ensureDocumentReviewSessionsSchema, ensureWorkspaceSchema } from './taskSchemaMigrations';
4
6
  const openDbs = [];
@@ -208,3 +210,16 @@ describe('ensureDocumentReviewSessionsSchema', () => {
208
210
  expect(row?.author_actor_id).toBe('user-1');
209
211
  });
210
212
  });
213
+ describe('postgres bootstrap parity', () => {
214
+ it('includes workspace asset tables and target_type indexes', () => {
215
+ const sqlPath = path.resolve(process.cwd(), 'src/migrations/postgres/001_init.sql');
216
+ const sql = fs.readFileSync(sqlPath, 'utf8');
217
+ expect(sql).toContain('CREATE TABLE IF NOT EXISTS workspace_assets');
218
+ expect(sql).toContain('CREATE TABLE IF NOT EXISTS workspace_asset_links');
219
+ expect(sql).toContain('target_type TEXT NOT NULL DEFAULT \'task\'');
220
+ expect(sql).toContain('display_name TEXT');
221
+ expect(sql).toContain('reference_number INTEGER');
222
+ expect(sql).toContain('CREATE INDEX IF NOT EXISTS idx_workspace_asset_links_target');
223
+ expect(sql).toContain('CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_assets_workspace_kind_reference');
224
+ });
225
+ });
@@ -284,7 +284,7 @@ export const workflowDocs = [
284
284
  ' - `### Next Action`',
285
285
  '6. Ask whether to save as `{artifacts.implementationPlan.path}`.',
286
286
  '7. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "implementation-plan.md"`.',
287
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
287
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
288
288
  '8. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
289
289
  '9. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
290
290
  '10. Print `prompts.handoffPrompt` and stop.'
@@ -358,7 +358,7 @@ export const workflowDocs = [
358
358
  ' - `### Next Step`',
359
359
  '4. Ask whether to save as `{artifacts.collaborationBlueprint.path}`.',
360
360
  '5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "collaboration-blueprint.md"`.',
361
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
361
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
362
362
  '6. Ask concise clarification questions only if required fields above are missing.',
363
363
  '7. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
364
364
  '8. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
@@ -435,14 +435,14 @@ export const workflowDocs = [
435
435
  ' - `### Next Step`',
436
436
  '4. Ask whether to save as `{artifacts.evaluationReport.path}`.',
437
437
  '5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "evaluation.md"`.',
438
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
438
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
439
439
  '6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
440
440
  '',
441
441
  '## 3. Optional Report Artifact',
442
442
  '',
443
443
  '1. Use report files only when user opts in.',
444
444
  '2. Save to `task attachment "evaluation.md"` and attach to task context when approved.',
445
- ' - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.',
445
+ ' - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.',
446
446
  '3. Stop.'
447
447
  ].join('\n')
448
448
  }
@@ -513,7 +513,7 @@ export const workflowDocs = [
513
513
  ' - `### Next Status`',
514
514
  '3. Ask whether to save as `{artifacts.reviewReport.path}`.',
515
515
  '4. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "review.md"`.',
516
- ' - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).',
516
+ ' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
517
517
  '5. Keep status within allowed statuses (`task`, `on-hold`, `in-progress`, `review`, `done`) unless user explicitly instructs otherwise.',
518
518
  ' - If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
519
519
  '6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
@@ -522,7 +522,7 @@ export const workflowDocs = [
522
522
  '',
523
523
  '1. Use report files only when user opts in.',
524
524
  '2. Save to `task attachment "review.md"` and attach to task context when approved.',
525
- ' - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.',
525
+ ' - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.',
526
526
  '3. Stop.'
527
527
  ].join('\n')
528
528
  }
@@ -102,7 +102,7 @@ content:
102
102
  - `### Next Step`
103
103
  4. Ask whether to save as `{artifacts.collaborationBlueprint.path}`.
104
104
  5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "collaboration-blueprint.md"`.
105
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
105
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
106
106
  6. Ask concise clarification questions only if required fields above are missing.
107
107
  7. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
108
108
  8. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
@@ -106,12 +106,12 @@ content:
106
106
  - `### Next Step`
107
107
  4. Ask whether to save as `{artifacts.evaluationReport.path}`.
108
108
  5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "evaluation.md"`.
109
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
109
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
110
110
  6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
111
111
 
112
112
  ## 3. Optional Report Artifact
113
113
 
114
114
  1. Use report files only when user opts in.
115
115
  2. Save to `task attachment "evaluation.md"` and attach to task context when approved.
116
- - If the document is not task-specific, store it under `docs/` and optionally link it with `{{MCP_PREFIX}}link_task_context`.
116
+ - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.
117
117
  3. Stop.
@@ -113,7 +113,7 @@ content:
113
113
  - `### Next Action`
114
114
  6. Ask whether to save as `{artifacts.implementationPlan.path}`.
115
115
  7. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "implementation-plan.md"`.
116
- - Use `{{MCP_PREFIX}}link_task_context` only for linking existing files/URLs (for example, shared docs under `docs/`).
116
+ - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
117
117
  8. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
118
118
  9. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
119
119
  10. Print `prompts.handoffPrompt` and stop.