@taskforcehq/taskforce 0.3.170 → 0.3.300

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 (696) hide show
  1. package/README.md +52 -21
  2. package/dist/Taskforce.module.css +3394 -5981
  3. package/dist/TaskforceCore.CategoryFallback.test.js +5 -2
  4. package/dist/TaskforceCore.filter-persistence.test.js +402 -0
  5. package/dist/TaskforceCore.js +388 -71
  6. package/dist/TaskforceCore.routing.test.js +311 -0
  7. package/dist/TaskforceCore.test.js +3344 -615
  8. package/dist/TaskforceWidget.js +3 -2
  9. package/dist/__tests__/localizationCatalogs.test.js +48 -31
  10. package/dist/__tests__/workflowSimulation.test.js +2 -2
  11. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.d.ts +60 -0
  12. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +324 -0
  13. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.test.js +278 -0
  14. package/dist/annotatedAttachments/payload.d.ts +2 -0
  15. package/dist/annotatedAttachments/payload.js +54 -0
  16. package/dist/annotatedAttachments/payload.test.js +67 -0
  17. package/dist/annotatedAttachments/service.d.ts +49 -0
  18. package/dist/annotatedAttachments/service.js +121 -0
  19. package/dist/annotatedAttachments/types.d.ts +86 -0
  20. package/dist/cli.js +74 -25
  21. package/dist/compat/deploymentCompat.d.ts +12 -0
  22. package/dist/compat/deploymentCompat.js +43 -0
  23. package/dist/compat/workspaceSyncCompat.d.ts +6 -0
  24. package/dist/compat/workspaceSyncCompat.js +79 -0
  25. package/dist/compat/workspaceSyncCompat.test.js +87 -0
  26. package/dist/components/features/AgentsModule.d.ts +5 -0
  27. package/dist/components/features/AgentsModule.js +131 -0
  28. package/dist/components/features/AgentsModule.test.js +102 -0
  29. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +24 -0
  30. package/dist/components/features/AnnotatedAttachmentWorkspace.js +1942 -0
  31. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +2831 -0
  32. package/dist/components/features/DocumentGenerateModal.js +8 -16
  33. package/dist/components/features/DocumentIndex.d.ts +3 -4
  34. package/dist/components/features/DocumentIndex.js +22 -10
  35. package/dist/components/features/DocumentViewer.d.ts +6 -2
  36. package/dist/components/features/DocumentViewer.js +1000 -18
  37. package/dist/components/features/DocumentWorkspace.d.ts +40 -2
  38. package/dist/components/features/DocumentWorkspace.js +96 -16
  39. package/dist/components/features/DocumentWorkspace.test.js +1202 -0
  40. package/dist/components/features/InitiativesModule.d.ts +22 -0
  41. package/dist/components/features/InitiativesModule.js +33 -0
  42. package/dist/components/features/TaskSettings.d.ts +41 -32
  43. package/dist/components/features/TaskSettings.js +798 -313
  44. package/dist/components/features/TaskSettings.test.js +1221 -47
  45. package/dist/components/features/WorkflowsModule.d.ts +27 -0
  46. package/dist/components/features/WorkflowsModule.js +21 -0
  47. package/dist/components/features/documentWorkspaceFilters.d.ts +10 -0
  48. package/dist/components/features/documentWorkspaceFilters.js +11 -0
  49. package/dist/components/features/settings/CategoryManager.d.ts +2 -0
  50. package/dist/components/features/settings/CategoryManager.js +15 -8
  51. package/dist/components/features/settings/PriorityManager.d.ts +18 -0
  52. package/dist/components/features/settings/PriorityManager.js +51 -0
  53. package/dist/components/features/settings/TaxonomyEditor.d.ts +2 -1
  54. package/dist/components/features/settings/TaxonomyEditor.js +41 -18
  55. package/dist/components/features/settings/TaxonomyLibraryManager.d.ts +26 -0
  56. package/dist/components/features/settings/TaxonomyLibraryManager.js +301 -0
  57. package/dist/components/features/settings/TaxonomyLibraryManager.test.js +141 -0
  58. package/dist/components/features/settings/TaxonomyManager.d.ts +35 -12
  59. package/dist/components/features/settings/TaxonomyManager.js +59 -27
  60. package/dist/components/features/settings/TypeManager.d.ts +11 -0
  61. package/dist/components/features/settings/TypeManager.js +48 -11
  62. package/dist/components/features/settings/{WorkflowEditorPrototype.d.ts → WorkflowEditor.d.ts} +2 -2
  63. package/dist/components/features/settings/{WorkflowEditorPrototype.js → WorkflowEditor.js} +3 -3
  64. package/dist/components/task/TaskActionHeader.d.ts +12 -2
  65. package/dist/components/task/TaskActionHeader.js +64 -8
  66. package/dist/components/task/TaskActionHeader.test.js +73 -0
  67. package/dist/components/task/TaskCard.d.ts +14 -16
  68. package/dist/components/task/TaskCard.js +144 -174
  69. package/dist/components/task/TaskCard.test.js +416 -64
  70. package/dist/components/task/TaskContextUpload.d.ts +6 -5
  71. package/dist/components/task/TaskContextUpload.js +199 -64
  72. package/dist/components/task/TaskContextUpload.test.js +331 -14
  73. package/dist/components/task/TaskForm.d.ts +23 -29
  74. package/dist/components/task/TaskForm.js +348 -169
  75. package/dist/components/task/TaskForm.test.js +419 -23
  76. package/dist/components/task/TaskKanban.d.ts +20 -21
  77. package/dist/components/task/TaskKanban.js +176 -316
  78. package/dist/components/task/TaskKanban.planning-drop.test.js +93 -0
  79. package/dist/components/task/TaskList.d.ts +22 -11
  80. package/dist/components/task/TaskList.js +98 -12
  81. package/dist/components/task/TaskList.test.js +206 -7
  82. package/dist/components/task/TaskReferenceBadge.d.ts +12 -0
  83. package/dist/components/task/TaskReferenceBadge.js +5 -0
  84. package/dist/components/task/TaskStatusActions.d.ts +12 -0
  85. package/dist/components/task/TaskStatusActions.js +18 -0
  86. package/dist/components/task/TaskStatusActions.test.js +45 -0
  87. package/dist/components/ui/ImageReferenceBadge.d.ts +12 -0
  88. package/dist/components/ui/ImageReferenceBadge.js +5 -0
  89. package/dist/components/ui/LevelSelector.d.ts +2 -1
  90. package/dist/components/ui/LevelSelector.js +2 -2
  91. package/dist/components/ui/Markdown.d.ts +1 -2
  92. package/dist/components/ui/Markdown.js +2 -13
  93. package/dist/components/ui/Modal.d.ts +3 -2
  94. package/dist/components/ui/Modal.js +4 -3
  95. package/dist/components/ui/MultiSelectFilter.d.ts +3 -1
  96. package/dist/components/ui/MultiSelectFilter.js +2 -2
  97. package/dist/components/ui/ReferenceBadgeButton.d.ts +13 -0
  98. package/dist/components/ui/ReferenceBadgeButton.js +6 -0
  99. package/dist/components/ui/TaxonomyDropdown.d.ts +7 -1
  100. package/dist/components/ui/TaxonomyDropdown.js +58 -23
  101. package/dist/components/ui/TopNoticeLayer.d.ts +7 -0
  102. package/dist/components/ui/TopNoticeLayer.js +14 -0
  103. package/dist/components/ui/TopNoticeLayer.test.js +25 -0
  104. package/dist/components/views/AppShellHeader.d.ts +13 -0
  105. package/dist/components/views/AppShellHeader.js +19 -0
  106. package/dist/components/views/AppShellHeader.test.js +21 -0
  107. package/dist/components/views/PlanComparisonPage.d.ts +73 -0
  108. package/dist/components/views/PlanComparisonPage.js +196 -0
  109. package/dist/components/views/PlanComparisonPage.test.js +251 -0
  110. package/dist/components/views/PlansPage.d.ts +14 -0
  111. package/dist/components/views/PlansPage.js +355 -0
  112. package/dist/components/views/StandaloneLayout.d.ts +2 -2
  113. package/dist/components/views/StandaloneLayout.js +2212 -1194
  114. package/dist/components/views/WidgetView.d.ts +2 -2
  115. package/dist/components/views/WidgetView.js +149 -43
  116. package/dist/components/views/chrome/WorkspaceChromeSections.d.ts +57 -0
  117. package/dist/components/views/chrome/WorkspaceChromeSections.js +38 -0
  118. package/dist/components/views/chrome/WorkspaceChromeSections.test.js +54 -0
  119. package/dist/components/views/chrome/workspaceChrome.d.ts +31 -0
  120. package/dist/components/views/chrome/workspaceChrome.js +108 -0
  121. package/dist/components/views/chrome/workspaceChrome.test.js +52 -0
  122. package/dist/components/views/panels/DocumentFilterToolbar.d.ts +10 -0
  123. package/dist/components/views/panels/DocumentFilterToolbar.js +7 -0
  124. package/dist/components/views/panels/DocumentFilterToolbar.test.js +19 -0
  125. package/dist/components/views/panels/FilterToolbar.d.ts +66 -0
  126. package/dist/components/views/panels/FilterToolbar.js +21 -0
  127. package/dist/components/views/panels/FilterToolbar.test.d.ts +1 -0
  128. package/dist/components/views/panels/FilterToolbar.test.js +45 -0
  129. package/dist/components/views/panels/FilterToolbarControls.d.ts +46 -0
  130. package/dist/components/views/panels/FilterToolbarControls.js +61 -0
  131. package/dist/components/views/panels/PlanningDrawer.d.ts +115 -0
  132. package/dist/components/views/panels/PlanningDrawer.js +220 -0
  133. package/dist/components/views/panels/ScheduleSidebar.d.ts +52 -0
  134. package/dist/components/views/panels/ScheduleSidebar.js +127 -0
  135. package/dist/components/views/panels/scheduleUtils.d.ts +14 -0
  136. package/dist/components/views/panels/scheduleUtils.js +79 -0
  137. package/dist/components/views/teamManagementAccess.d.ts +6 -0
  138. package/dist/components/views/teamManagementAccess.js +18 -0
  139. package/dist/components/views/teamManagementAccess.test.d.ts +1 -0
  140. package/dist/components/views/teamManagementAccess.test.js +44 -0
  141. package/dist/config/clientDeployment.d.ts +2 -0
  142. package/dist/config/clientDeployment.js +13 -0
  143. package/dist/config/cloudEnvironment.d.ts +15 -0
  144. package/dist/config/cloudEnvironment.js +60 -0
  145. package/dist/config/deployment.d.ts +20 -0
  146. package/dist/config/deployment.js +67 -0
  147. package/dist/config/deployment.test.d.ts +1 -0
  148. package/dist/config/deployment.test.js +88 -0
  149. package/dist/config/envSchema.js +36 -8
  150. package/dist/config/envSchema.test.js +28 -0
  151. package/dist/core/AiProfileService.d.ts +66 -0
  152. package/dist/core/AiProfileService.js +320 -0
  153. package/dist/core/AiProfileService.test.d.ts +1 -0
  154. package/dist/core/AiProfileService.test.js +164 -0
  155. package/dist/core/AiProfiles.test.d.ts +1 -0
  156. package/dist/core/AiProfiles.test.js +449 -0
  157. package/dist/core/AttachmentLinkService.d.ts +15 -0
  158. package/dist/core/AttachmentLinkService.js +157 -0
  159. package/dist/core/AuthTokenService.d.ts +44 -0
  160. package/dist/core/AuthTokenService.js +207 -0
  161. package/dist/core/CreatedBy.test.js +134 -6
  162. package/dist/core/DeletedTaskLifecycleService.d.ts +33 -0
  163. package/dist/core/DeletedTaskLifecycleService.js +158 -0
  164. package/dist/core/DeletedTaskTrash.test.d.ts +1 -0
  165. package/dist/core/DeletedTaskTrash.test.js +104 -0
  166. package/dist/core/EntitlementsPolicy.test.js +78 -5
  167. package/dist/core/GlobalSettingsService.d.ts +16 -0
  168. package/dist/core/GlobalSettingsService.js +370 -0
  169. package/dist/core/JsonBackupRuntime.test.d.ts +1 -0
  170. package/dist/core/JsonBackupRuntime.test.js +155 -0
  171. package/dist/core/McpTokenService.d.ts +118 -0
  172. package/dist/core/McpTokenService.js +921 -0
  173. package/dist/core/PlanEntitlementService.d.ts +201 -0
  174. package/dist/core/PlanEntitlementService.js +1442 -0
  175. package/dist/core/PlanVersionPolicy.test.d.ts +1 -0
  176. package/dist/core/PlanVersionPolicy.test.js +178 -0
  177. package/dist/core/PlanningEntities.test.d.ts +1 -0
  178. package/dist/core/PlanningEntities.test.js +95 -0
  179. package/dist/core/ScheduleFields.test.js +15 -19
  180. package/dist/core/SignupMonetizationSettings.test.d.ts +1 -0
  181. package/dist/core/SignupMonetizationSettings.test.js +159 -0
  182. package/dist/core/Stats.test.d.ts +1 -0
  183. package/dist/core/Stats.test.js +36 -0
  184. package/dist/core/SyncReconciliationService.d.ts +93 -0
  185. package/dist/core/SyncReconciliationService.js +406 -0
  186. package/dist/core/SystemAdmin.test.js +578 -13
  187. package/dist/core/TaskActivityService.d.ts +21 -0
  188. package/dist/core/TaskActivityService.js +130 -0
  189. package/dist/core/TaskAttachmentsCanonical.test.d.ts +1 -0
  190. package/dist/core/TaskAttachmentsCanonical.test.js +306 -0
  191. package/dist/core/TaskAuditTimeline.test.d.ts +1 -0
  192. package/dist/core/TaskAuditTimeline.test.js +132 -0
  193. package/dist/core/TaskTaxonomyValidation.test.js +338 -15
  194. package/dist/core/Taskforce.d.ts +930 -183
  195. package/dist/core/Taskforce.ids.test.js +252 -0
  196. package/dist/core/Taskforce.js +3848 -2532
  197. package/dist/core/Taskforce.mcpAuth.test.d.ts +1 -0
  198. package/dist/core/Taskforce.mcpAuth.test.js +343 -0
  199. package/dist/core/Taskforce.realtimeMutation.test.js +57 -2
  200. package/dist/core/TaxonomySettingsService.d.ts +18 -0
  201. package/dist/core/TaxonomySettingsService.js +162 -0
  202. package/dist/core/WorkspaceDelete.test.js +32 -13
  203. package/dist/core/WorkspaceLifecycleService.d.ts +11 -0
  204. package/dist/core/WorkspaceLifecycleService.js +88 -0
  205. package/dist/core/WorkspacePermissions.test.js +95 -0
  206. package/dist/core/WorkspacePlanMode.test.js +114 -1
  207. package/dist/core/WorkspacePreferenceService.d.ts +41 -0
  208. package/dist/core/WorkspacePreferenceService.js +246 -0
  209. package/dist/core/WorkspaceSyncSettings.test.d.ts +1 -0
  210. package/dist/core/WorkspaceSyncSettings.test.js +65 -0
  211. package/dist/core/__tests__/TaskAttachmentsCanonical.test.d.ts +1 -0
  212. package/dist/core/__tests__/TaskAttachmentsCanonical.test.js +212 -0
  213. package/dist/core/shared.d.ts +36 -0
  214. package/dist/core/shared.js +128 -0
  215. package/dist/core/types.d.ts +614 -0
  216. package/dist/core/types.js +27 -0
  217. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +56 -0
  218. package/dist/documentReviews/DocumentReviewCommentStore.js +230 -0
  219. package/dist/documentReviews/DocumentReviewSessionStore.d.ts +52 -0
  220. package/dist/documentReviews/DocumentReviewSessionStore.js +193 -0
  221. package/dist/documentReviews/DocumentReviewSessionStore.test.d.ts +1 -0
  222. package/dist/documentReviews/DocumentReviewSessionStore.test.js +127 -0
  223. package/dist/documentReviews/service.d.ts +68 -0
  224. package/dist/documentReviews/service.js +210 -0
  225. package/dist/documentReviews/types.d.ts +58 -0
  226. package/dist/documentReviews/types.js +1 -0
  227. package/dist/hooks/auth/useAuthGuardPolicy.d.ts +2 -0
  228. package/dist/hooks/auth/useAuthGuardPolicy.js +1 -0
  229. package/dist/hooks/tasks/useCurrentTaskRelations.d.ts +15 -0
  230. package/dist/hooks/tasks/useCurrentTaskRelations.js +37 -0
  231. package/dist/hooks/tasks/useTaskActions.d.ts +3 -0
  232. package/dist/hooks/tasks/useTaskActions.js +2 -0
  233. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +65 -0
  234. package/dist/hooks/tasks/useTaskEditorNavigation.js +235 -0
  235. package/dist/hooks/tasks/useTaskFilters.d.ts +2 -0
  236. package/dist/hooks/tasks/useTaskFilters.js +2 -0
  237. package/dist/hooks/tasks/useTaskFormActions.d.ts +58 -0
  238. package/dist/hooks/tasks/useTaskFormActions.js +365 -0
  239. package/dist/hooks/tasks/useTaskRelationships.d.ts +16 -0
  240. package/dist/hooks/tasks/useTaskRelationships.js +64 -0
  241. package/dist/hooks/ui/useResourceExport.d.ts +19 -0
  242. package/dist/hooks/ui/useResourceExport.js +84 -0
  243. package/dist/hooks/ui/useSettingsModel.d.ts +203 -0
  244. package/dist/hooks/ui/useSettingsModel.js +125 -0
  245. package/dist/hooks/ui/useSettingsPersistence.d.ts +36 -0
  246. package/dist/hooks/ui/useSettingsPersistence.js +254 -0
  247. package/dist/hooks/ui/useSettingsTaxonomyManagement.d.ts +119 -0
  248. package/dist/hooks/ui/useSettingsTaxonomyManagement.js +536 -0
  249. package/dist/hooks/ui/useUiNotice.d.ts +1 -0
  250. package/dist/hooks/ui/useUiNotice.js +1 -0
  251. package/dist/hooks/ui/useWorkflowTemplates.d.ts +37 -0
  252. package/dist/hooks/ui/useWorkflowTemplates.js +111 -0
  253. package/dist/hooks/ui/useZenMode.d.ts +5 -0
  254. package/dist/hooks/ui/useZenMode.js +32 -0
  255. package/dist/hooks/useFilterSort.d.ts +60 -0
  256. package/dist/hooks/useFilterSort.js +362 -0
  257. package/dist/hooks/useFilterSort.test.d.ts +1 -0
  258. package/dist/hooks/useFilterSort.test.js +333 -0
  259. package/dist/hooks/useRealtimeSync.d.ts +1 -0
  260. package/dist/hooks/useRealtimeSync.js +24 -9
  261. package/dist/hooks/useRealtimeSync.test.js +28 -1
  262. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.d.ts +1 -0
  263. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +34 -0
  264. package/dist/hooks/useSyncOrchestrator.d.ts +65 -103
  265. package/dist/hooks/useSyncOrchestrator.js +1538 -670
  266. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +700 -174
  267. package/dist/hooks/useTaskData.d.ts +35 -0
  268. package/dist/hooks/useTaskData.js +239 -0
  269. package/dist/hooks/useTaskData.test.d.ts +1 -0
  270. package/dist/hooks/useTaskData.test.js +119 -0
  271. package/dist/hooks/useTaskMutations.d.ts +46 -0
  272. package/dist/hooks/useTaskMutations.js +472 -0
  273. package/dist/hooks/useTaskMutations.test.d.ts +1 -0
  274. package/dist/hooks/useTaskMutations.test.js +80 -0
  275. package/dist/hooks/useTaskforce.contract.test.d.ts +1 -0
  276. package/dist/hooks/useTaskforce.contract.test.js +7 -0
  277. package/dist/hooks/useTaskforce.d.ts +260 -295
  278. package/dist/hooks/useTaskforce.js +1954 -2623
  279. package/dist/hooks/useTaskforce.priority-filters.test.js +6 -11
  280. package/dist/hooks/useTaskforce.sync-behavior.test.d.ts +1 -0
  281. package/dist/hooks/useTaskforce.sync-behavior.test.js +1120 -0
  282. package/dist/hooks/useUiNotice.d.ts +16 -0
  283. package/dist/hooks/useUiNotice.js +49 -0
  284. package/dist/hooks/useWorkspaceSyncController.d.ts +23 -46
  285. package/dist/hooks/useWorkspaceSyncController.js +280 -461
  286. package/dist/hooks/useWorkspaceSyncController.test.js +106 -199
  287. package/dist/hooks/workspace/useTaskforceApiRouting.d.ts +8 -0
  288. package/dist/hooks/workspace/useTaskforceApiRouting.js +91 -0
  289. package/dist/hooks/workspace/useTaskforceApiRouting.test.d.ts +1 -0
  290. package/dist/hooks/workspace/useTaskforceApiRouting.test.js +60 -0
  291. package/dist/hooks/workspace/useWorkspaceSyncController.d.ts +1 -0
  292. package/dist/hooks/workspace/useWorkspaceSyncController.js +1 -0
  293. package/dist/hooks/workspace/workspaceLocalState.d.ts +30 -0
  294. package/dist/hooks/workspace/workspaceLocalState.js +101 -0
  295. package/dist/localization/locales/en-US.d.ts +1 -8
  296. package/dist/localization/locales/en-US.js +4 -11
  297. package/dist/localization/locales/es-419.js +2 -9
  298. package/dist/localization/locales/pt-BR.js +2 -9
  299. package/dist/localization/localizationCatalogs.test.d.ts +1 -0
  300. package/dist/localization/localizationCatalogs.test.js +37 -0
  301. package/dist/main.d.ts +1 -0
  302. package/dist/main.js +9 -15
  303. package/dist/mcp/clientIntegrations.d.ts +33 -0
  304. package/dist/mcp/clientIntegrations.js +199 -0
  305. package/dist/mcp/clientIntegrations.test.d.ts +1 -0
  306. package/dist/mcp/clientIntegrations.test.js +110 -0
  307. package/dist/mcp/index.d.ts +2 -0
  308. package/dist/mcp/index.js +2 -0
  309. package/dist/mcp/optionResolution.test.js +6 -2
  310. package/dist/mcp/runtime.d.ts +120 -0
  311. package/dist/mcp/runtime.js +5668 -0
  312. package/dist/mcp/runtime.test.d.ts +1 -0
  313. package/dist/mcp/runtime.test.js +3293 -0
  314. package/dist/mcp/server.js +2 -1793
  315. package/dist/mcp/structuredCommentValidation.test.d.ts +1 -0
  316. package/dist/{__tests__ → mcp}/structuredCommentValidation.test.js +1 -1
  317. package/dist/mcp/structuredDocValidation.js +1 -2
  318. package/dist/mcp/structuredDocValidation.test.d.ts +1 -0
  319. package/dist/{__tests__ → mcp}/structuredDocValidation.test.js +9 -4
  320. package/dist/mcp/toolRegistry.d.ts +570 -0
  321. package/dist/mcp/toolRegistry.js +90 -0
  322. package/dist/mcp/toolRegistry.test.d.ts +1 -0
  323. package/dist/mcp/toolRegistry.test.js +30 -0
  324. package/dist/migrations/billingSchemaParity.test.js +111 -0
  325. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  326. package/dist/migrations/taskSchemaMigrations.js +681 -39
  327. package/dist/migrations/taskSchemaMigrations.test.d.ts +1 -0
  328. package/dist/migrations/taskSchemaMigrations.test.js +210 -0
  329. package/dist/plugins/vite.js +13 -7
  330. package/dist/public/apple-touch-icon.png +0 -0
  331. package/dist/public/archive/phoenix/apple-touch-icon.png +0 -0
  332. package/dist/public/archive/phoenix/favicon.ico +0 -0
  333. package/dist/public/archive/phoenix/site.webmanifest +1 -0
  334. package/dist/public/favicon-96x96.png +0 -0
  335. package/dist/public/favicon.ico +0 -0
  336. package/dist/public/favicon.svg +17 -0
  337. package/dist/public/site.webmanifest +21 -1
  338. package/dist/public/web-app-manifest-192x192.png +0 -0
  339. package/dist/public/web-app-manifest-512x512.png +0 -0
  340. package/dist/releaseVersion.test.d.ts +1 -0
  341. package/dist/{__tests__/releaseVersion.test.js → releaseVersion.test.js} +1 -1
  342. package/dist/resources/templates/WORKFLOW_V2_POLICY.md +1 -1
  343. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +62 -52
  344. package/dist/resources/templates/workflows/collaborate.yaml +11 -5
  345. package/dist/resources/templates/workflows/do.yaml +8 -2
  346. package/dist/resources/templates/workflows/evaluate.yaml +13 -7
  347. package/dist/resources/templates/workflows/execute.yaml +40 -23
  348. package/dist/resources/templates/workflows/plan.yaml +15 -8
  349. package/dist/resources/templates/workflows/review.yaml +14 -8
  350. package/dist/runtime/appGateDefinitions.d.ts +32 -0
  351. package/dist/runtime/appGateDefinitions.js +32 -0
  352. package/dist/runtime/appGates.d.ts +29 -0
  353. package/dist/runtime/appGates.js +53 -0
  354. package/dist/runtime/appGates.test.d.ts +1 -0
  355. package/dist/runtime/appGates.test.js +42 -0
  356. package/dist/runtime/migrationFlags.d.ts +1 -0
  357. package/dist/runtime/migrationFlags.js +1 -0
  358. package/dist/server/annotatedAttachmentsRoutes.test.d.ts +1 -0
  359. package/dist/server/annotatedAttachmentsRoutes.test.js +473 -0
  360. package/dist/server/auth.js +14 -2
  361. package/dist/server/auth.test.js +21 -1
  362. package/dist/server/cors.js +11 -5
  363. package/dist/server/cors.test.js +6 -0
  364. package/dist/server/documentReviewRoutes.test.d.ts +1 -0
  365. package/dist/server/documentReviewRoutes.test.js +157 -0
  366. package/dist/server/index.cookieProxy.test.js +46 -1
  367. package/dist/server/index.d.ts +20 -0
  368. package/dist/server/index.js +168 -41
  369. package/dist/server/index.rateLimit.test.js +6 -0
  370. package/dist/server/index.test.js +133 -2
  371. package/dist/server/mockStripe.d.ts +72 -0
  372. package/dist/server/mockStripe.js +357 -0
  373. package/dist/server/realtimeSyncWs.js +4 -0
  374. package/dist/server/routes/admin.d.ts +114 -0
  375. package/dist/server/routes/admin.js +2226 -0
  376. package/dist/server/routes/annotatedAttachments.d.ts +24 -0
  377. package/dist/server/routes/annotatedAttachments.js +235 -0
  378. package/dist/server/routes/auth.d.ts +61 -0
  379. package/dist/server/routes/auth.js +1296 -0
  380. package/dist/server/{routes.billing.d.ts → routes/billing.d.ts} +3 -2
  381. package/dist/server/routes/billing.js +2001 -0
  382. package/dist/server/routes/billing.test.d.ts +1 -0
  383. package/dist/server/routes/billing.test.js +1631 -0
  384. package/dist/server/routes/documentReviews.d.ts +11 -0
  385. package/dist/server/routes/documentReviews.js +191 -0
  386. package/dist/server/routes/documents.d.ts +118 -0
  387. package/dist/server/routes/documents.js +1113 -0
  388. package/dist/server/routes/resources.d.ts +25 -0
  389. package/dist/server/routes/resources.js +225 -0
  390. package/dist/server/routes/shared.d.ts +35 -0
  391. package/dist/server/routes/shared.js +305 -0
  392. package/dist/server/routes/shared.test.d.ts +1 -0
  393. package/dist/server/routes/shared.test.js +32 -0
  394. package/dist/server/{routes.sync.d.ts → routes/sync.d.ts} +5 -5
  395. package/dist/server/routes/sync.integration.test.d.ts +1 -0
  396. package/dist/server/routes/sync.integration.test.js +2003 -0
  397. package/dist/server/routes/sync.js +3143 -0
  398. package/dist/server/routes/tasks.d.ts +72 -0
  399. package/dist/server/routes/tasks.js +1252 -0
  400. package/dist/server/routes/workspaces.d.ts +32 -0
  401. package/dist/server/routes/workspaces.js +307 -0
  402. package/dist/server/routes.d.ts +8 -9
  403. package/dist/server/routes.js +968 -4092
  404. package/dist/server/routes.test.js +9043 -2415
  405. package/dist/server/runtimeMode.d.ts +1 -1
  406. package/dist/server/runtimeMode.js +3 -18
  407. package/dist/server/runtimeMode.test.js +3 -3
  408. package/dist/server/securityHeaders.d.ts +1 -1
  409. package/dist/server/securityHeaders.js +65 -6
  410. package/dist/server/securityHeaders.test.js +40 -2
  411. package/dist/services/templateEngine.test.d.ts +1 -0
  412. package/dist/{__tests__ → services}/templateEngine.test.js +1 -1
  413. package/dist/services/templates.test.d.ts +1 -0
  414. package/dist/{__tests__ → services}/templates.test.js +1 -1
  415. package/dist/services/workflowDocumentFixtures.test.d.ts +1 -0
  416. package/dist/{__tests__ → services}/workflowDocumentFixtures.test.js +4 -4
  417. package/dist/services/workflowExportMatrix.test.d.ts +1 -0
  418. package/dist/{__tests__ → services}/workflowExportMatrix.test.js +1 -1
  419. package/dist/services/workflowExportSnapshots.test.d.ts +1 -0
  420. package/dist/services/workflowGeneration.test.d.ts +1 -0
  421. package/dist/services/workflowSimulation.test.d.ts +1 -0
  422. package/dist/services/workflowSimulation.test.js +113 -0
  423. package/dist/services/workflowV2Policy.test.d.ts +1 -0
  424. package/dist/{__tests__ → services}/workflowV2Policy.test.js +2 -2
  425. package/dist/shared/aiProfileSurfaceType.d.ts +9 -0
  426. package/dist/shared/aiProfileSurfaceType.js +49 -0
  427. package/dist/shared/customTaxonomyLibrary.d.ts +11 -0
  428. package/dist/shared/customTaxonomyLibrary.js +276 -0
  429. package/dist/shared/customTaxonomyLibrary.test.d.ts +1 -0
  430. package/dist/shared/customTaxonomyLibrary.test.js +20 -0
  431. package/dist/shared/taxonomyCatalog.d.ts +19 -0
  432. package/dist/shared/taxonomyCatalog.js +36 -0
  433. package/dist/shared/taxonomyDefaults.d.ts +29 -0
  434. package/dist/shared/taxonomyDefaults.js +26 -0
  435. package/dist/shared/taxonomyLibrary.d.ts +15 -0
  436. package/dist/shared/taxonomyLibrary.js +98 -0
  437. package/dist/shared/taxonomyLibrary.test.d.ts +1 -0
  438. package/dist/shared/taxonomyLibrary.test.js +26 -0
  439. package/dist/shared/taxonomyState.d.ts +36 -0
  440. package/dist/shared/taxonomyState.js +73 -0
  441. package/dist/shared/taxonomyState.test.d.ts +1 -0
  442. package/dist/shared/taxonomyState.test.js +71 -0
  443. package/dist/shared/workflowDefaults.d.ts +9 -0
  444. package/dist/shared/workflowDefaults.js +11 -0
  445. package/dist/storage/documentIntegrity.d.ts +2 -0
  446. package/dist/storage/documentIntegrity.js +34 -17
  447. package/dist/storage/documentPurge.d.ts +2 -1
  448. package/dist/storage/documentPurge.js +35 -8
  449. package/dist/storage/index.d.ts +4 -0
  450. package/dist/storage/index.js +2 -0
  451. package/dist/storage/objectStorage.d.ts +1 -1
  452. package/dist/storage/objectStorageClient.d.ts +6 -4
  453. package/dist/storage/objectStorageClient.js +77 -29
  454. package/dist/storage/objectStorageClient.test.d.ts +1 -0
  455. package/dist/storage/objectStorageClient.test.js +57 -0
  456. package/dist/storage/objectStorageConfig.js +3 -1
  457. package/dist/storage/objectStorageConfig.test.d.ts +1 -0
  458. package/dist/storage/objectStorageConfig.test.js +38 -0
  459. package/dist/storage/postgresAdapter.d.ts +5 -0
  460. package/dist/storage/postgresAdapter.js +2 -2
  461. package/dist/storage/postgresAdapter.test.d.ts +1 -0
  462. package/dist/storage/postgresAdapter.test.js +29 -0
  463. package/dist/storage/taskAssetStore.d.ts +7 -4
  464. package/dist/storage/taskAssetStore.js +65 -60
  465. package/dist/storage/workspaceAssetStore.d.ts +122 -0
  466. package/dist/storage/workspaceAssetStore.js +496 -0
  467. package/dist/storage/workspaceAssetStore.test.d.ts +1 -0
  468. package/dist/storage/workspaceAssetStore.test.js +501 -0
  469. package/dist/sync/cloudSyncApi.d.ts +33 -2
  470. package/dist/sync/cloudSyncApi.js +37 -15
  471. package/dist/sync/cloudSyncApi.test.js +60 -3
  472. package/dist/sync/index.d.ts +2 -0
  473. package/dist/sync/index.js +3 -0
  474. package/dist/sync/syncService.d.ts +25 -0
  475. package/dist/sync/syncService.js +184 -16
  476. package/dist/sync/syncService.test.js +289 -25
  477. package/dist/sync/workspaceRepair.d.ts +114 -0
  478. package/dist/sync/workspaceRepair.js +566 -0
  479. package/dist/sync/workspaceSyncModel.d.ts +230 -2
  480. package/dist/sync/workspaceSyncModel.js +456 -17
  481. package/dist/sync/workspaceSyncModel.test.js +642 -0
  482. package/dist/sync/workspaceSyncState.d.ts +12 -0
  483. package/dist/sync/workspaceSyncState.js +12 -0
  484. package/dist/sync/workspaceSyncSurface.d.ts +33 -0
  485. package/dist/sync/workspaceSyncSurface.js +74 -0
  486. package/dist/types.d.ts +143 -18
  487. package/dist/types.js +9 -24
  488. package/dist/ui/assets/AgentsModule-TVmCgizS.js +1 -0
  489. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +1 -0
  490. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CAyhnPeR.js +3 -0
  491. package/dist/ui/assets/DocumentWorkspace-BOCw5e4D.js +250 -0
  492. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +1 -0
  493. package/dist/ui/assets/InitiativesModule-CN0r02Oi.js +1 -0
  494. package/dist/ui/assets/PlansPage-BlVC_lRq.css +1 -0
  495. package/dist/ui/assets/PlansPage-FcQSNLZd.js +1 -0
  496. package/dist/ui/assets/TaskSettings-BwB9NtmJ.css +1 -0
  497. package/dist/ui/assets/TaskSettings-Cw5zYD1L.js +8 -0
  498. package/dist/ui/assets/WorkflowsModule-CY9R2zPB.js +5 -0
  499. package/dist/ui/assets/index-Bzqy5QGm.js +6 -0
  500. package/dist/ui/assets/index-DxRiI3tY.css +1 -0
  501. package/dist/ui/assets/vendor-dnd-DRzYolkg.js +5 -0
  502. package/dist/ui/assets/{vendor-icons-ZFG3SGwo.js → vendor-icons-QZyhEwgT.js} +1 -1
  503. package/dist/ui/assets/{vendor-markdown-CKYkQHfj.js → vendor-markdown-BUxTU7dS.js} +1 -1
  504. package/dist/ui/assets/vendor-react-CKJs5o3c.js +61 -0
  505. package/dist/ui/assets/vendor-router-BbWMxlnO.js +3 -0
  506. package/dist/ui/branding/logos/logo.png +0 -0
  507. package/dist/ui/branding/logos/logo_dark.svg +27 -0
  508. package/dist/ui/branding/logos/logo_favicon.svg +35 -0
  509. package/dist/ui/branding/logos/logo_light.svg +27 -0
  510. package/dist/ui/favicon/apple-touch-icon.png +0 -0
  511. package/dist/ui/favicon/archive/phoenix/apple-touch-icon.png +0 -0
  512. package/dist/ui/favicon/archive/phoenix/favicon.ico +0 -0
  513. package/dist/ui/favicon/archive/phoenix/site.webmanifest +1 -0
  514. package/dist/ui/favicon/favicon-96x96.png +0 -0
  515. package/dist/ui/favicon/favicon.ico +0 -0
  516. package/dist/ui/favicon/favicon.svg +17 -0
  517. package/dist/ui/favicon/site.webmanifest +21 -1
  518. package/dist/ui/favicon/web-app-manifest-192x192.png +0 -0
  519. package/dist/ui/favicon/web-app-manifest-512x512.png +0 -0
  520. package/dist/ui/index.html +10 -7
  521. package/dist/ui/product/screen_01.png +0 -0
  522. package/dist/ui/product/screen_02.png +0 -0
  523. package/dist/ui/product/screen_03.png +0 -0
  524. package/dist/utils/annotatedAttachments.d.ts +20 -0
  525. package/dist/utils/annotatedAttachments.js +74 -0
  526. package/dist/utils/annotatedAttachments.test.d.ts +1 -0
  527. package/dist/utils/annotatedAttachments.test.js +108 -0
  528. package/dist/utils/assignees.d.ts +26 -0
  529. package/dist/utils/assignees.js +132 -0
  530. package/dist/utils/canonicalAssetKind.d.ts +16 -0
  531. package/dist/utils/canonicalAssetKind.js +39 -0
  532. package/dist/utils/canonicalAssetKind.test.d.ts +1 -0
  533. package/dist/utils/canonicalAssetKind.test.js +24 -0
  534. package/dist/utils/coalescedRefresh.d.ts +5 -0
  535. package/dist/utils/coalescedRefresh.js +16 -0
  536. package/dist/utils/coalescedRefresh.test.d.ts +1 -0
  537. package/dist/utils/coalescedRefresh.test.js +30 -0
  538. package/dist/utils/constants.d.ts +16 -3
  539. package/dist/utils/constants.icons.test.js +2 -1
  540. package/dist/utils/constants.js +70 -13
  541. package/dist/utils/contextAssetEvents.d.ts +7 -0
  542. package/dist/utils/contextAssetEvents.js +6 -0
  543. package/dist/utils/contextFiles.d.ts +14 -3
  544. package/dist/utils/contextFiles.js +40 -8
  545. package/dist/utils/documentManagerApi.d.ts +6 -0
  546. package/dist/utils/documentManagerApi.js +19 -0
  547. package/dist/utils/documentNames.d.ts +24 -0
  548. package/dist/utils/documentNames.js +91 -0
  549. package/dist/utils/documentReferences.d.ts +9 -0
  550. package/dist/utils/documentReferences.js +11 -0
  551. package/dist/utils/entityReferences.d.ts +9 -0
  552. package/dist/utils/entityReferences.js +32 -0
  553. package/dist/utils/imageReferences.d.ts +9 -0
  554. package/dist/utils/imageReferences.js +11 -0
  555. package/dist/utils/planParser.d.ts +2 -2
  556. package/dist/utils/planParser.js +11 -11
  557. package/dist/utils/planParser.test.d.ts +1 -0
  558. package/dist/{__tests__ → utils}/planParser.test.js +22 -22
  559. package/dist/utils/planningReferences.d.ts +17 -0
  560. package/dist/utils/planningReferences.js +30 -0
  561. package/dist/utils/planningReferences.test.d.ts +1 -0
  562. package/dist/utils/planningReferences.test.js +17 -0
  563. package/dist/utils/taskActivity.d.ts +9 -0
  564. package/dist/utils/taskActivity.js +147 -0
  565. package/dist/utils/taskActivity.test.d.ts +1 -0
  566. package/dist/utils/taskActivity.test.js +34 -0
  567. package/dist/utils/taskDraftDefaults.d.ts +21 -0
  568. package/dist/utils/taskDraftDefaults.js +40 -0
  569. package/dist/utils/taskDraftDefaults.test.d.ts +1 -0
  570. package/dist/utils/taskDraftDefaults.test.js +34 -0
  571. package/dist/utils/taskNormalization.d.ts +25 -0
  572. package/dist/utils/taskNormalization.js +161 -0
  573. package/dist/utils/taskNormalization.test.d.ts +1 -0
  574. package/dist/utils/taskNormalization.test.js +158 -0
  575. package/dist/utils/taskReferences.d.ts +5 -0
  576. package/dist/utils/taskReferences.js +11 -0
  577. package/dist/utils/taskforceApiClient.d.ts +2 -0
  578. package/dist/utils/taskforceApiClient.js +101 -3
  579. package/dist/utils/taskforceApiClient.test.d.ts +1 -0
  580. package/dist/utils/taskforceApiClient.test.js +44 -0
  581. package/dist/utils/taxonomyFilterOptions.d.ts +2 -0
  582. package/dist/utils/taxonomyFilterOptions.js +17 -0
  583. package/dist/utils/taxonomyFormDefaults.d.ts +3 -0
  584. package/dist/utils/taxonomyFormDefaults.js +28 -0
  585. package/dist/utils/taxonomyFormDefaults.test.d.ts +1 -0
  586. package/dist/utils/taxonomyFormDefaults.test.js +63 -0
  587. package/dist/utils/taxonomyLifecycle.d.ts +3 -0
  588. package/dist/utils/taxonomyLifecycle.js +17 -0
  589. package/dist/utils/taxonomySorting.d.ts +7 -0
  590. package/dist/utils/taxonomySorting.js +74 -0
  591. package/dist/utils/theme.d.ts +15 -0
  592. package/dist/utils/theme.js +23 -0
  593. package/dist/utils/uiNotice.d.ts +7 -0
  594. package/dist/utils/uiNotice.js +6 -0
  595. package/dist/utils/uiNotice.test.d.ts +1 -0
  596. package/dist/utils/uiNotice.test.js +18 -0
  597. package/dist/utils/workspaceIdentity.d.ts +14 -0
  598. package/dist/utils/workspaceIdentity.js +21 -0
  599. package/dist/utils/workspaceIdentity.test.js +30 -1
  600. package/dist/utils/workspaceSyncPresentation.d.ts +20 -0
  601. package/dist/utils/workspaceSyncPresentation.js +21 -0
  602. package/dist/utils/workspaceSyncPresentation.test.d.ts +1 -0
  603. package/dist/utils/workspaceSyncPresentation.test.js +36 -0
  604. package/package.json +28 -23
  605. package/scripts/bootstrap-playwright-auth.mjs +155 -0
  606. package/scripts/check-compat-boundaries.mjs +41 -0
  607. package/scripts/check-env.ts +9 -2
  608. package/scripts/debug-login.mjs +32 -0
  609. package/scripts/migrate-planning-model.ts +233 -0
  610. package/scripts/migrate-task-data-assets.mjs +408 -0
  611. package/scripts/playwright-auth.sh +11 -0
  612. package/scripts/run-dev-proxy.sh +2 -0
  613. package/scripts/update-homebrew-formula.sh +2 -2
  614. package/scripts/with-esbuild.sh +11 -0
  615. package/src/resources/templates/WORKFLOW_V2_POLICY.md +1 -1
  616. package/src/resources/templates/workflow-sources/workflowDocs.mjs +62 -52
  617. package/src/resources/templates/workflows/collaborate.yaml +11 -5
  618. package/src/resources/templates/workflows/do.yaml +8 -2
  619. package/src/resources/templates/workflows/evaluate.yaml +13 -7
  620. package/src/resources/templates/workflows/execute.yaml +40 -23
  621. package/src/resources/templates/workflows/plan.yaml +15 -8
  622. package/src/resources/templates/workflows/review.yaml +14 -8
  623. package/dist/TaskforceScreenshot.d.ts +0 -11
  624. package/dist/TaskforceScreenshot.js +0 -113
  625. package/dist/compat/priorityCompat.d.ts +0 -2
  626. package/dist/compat/priorityCompat.js +0 -24
  627. package/dist/components/features/settings/TaxonomyManager 2.d.ts +0 -52
  628. package/dist/components/features/settings/TaxonomyManager 2.js +0 -75
  629. package/dist/components/task/TaskKanban 2.d.ts +0 -76
  630. package/dist/components/task/TaskKanban 2.js +0 -1004
  631. package/dist/components/task/TaskScreenshotSection.d.ts +0 -15
  632. package/dist/components/task/TaskScreenshotSection.js +0 -22
  633. package/dist/components/views/StandaloneLayout 2.d.ts +0 -8
  634. package/dist/components/views/StandaloneLayout 2.js +0 -1660
  635. package/dist/core/InitiativeTemplates.test.js +0 -50
  636. package/dist/core/ParentLifecycle.test.js +0 -98
  637. package/dist/migrations/clientMigrations.d.ts +0 -9
  638. package/dist/migrations/clientMigrations.js +0 -74
  639. package/dist/migrations/flags.d.ts +0 -6
  640. package/dist/migrations/flags.js +0 -8
  641. package/dist/migrations/taskMigrations.d.ts +0 -71
  642. package/dist/migrations/taskMigrations.js +0 -236
  643. package/dist/migrations/taskMigrations.test.js +0 -34
  644. package/dist/server/routes.billing.js +0 -991
  645. package/dist/server/routes.billing.test.js +0 -387
  646. package/dist/server/routes.sync.integration.test.js +0 -470
  647. package/dist/server/routes.sync.js +0 -1141
  648. package/dist/soak/syncSoakHarness.d.ts +0 -6
  649. package/dist/soak/syncSoakHarness.js +0 -10
  650. package/dist/ui/assets/index-0W5vyCpn.css +0 -1
  651. package/dist/ui/assets/index-MCZuNNfn.js +0 -23
  652. package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
  653. package/dist/ui/assets/vendor-dnd-BI1K77C1.js +0 -5
  654. package/dist/ui/assets/vendor-react-DdIDsh7f.js +0 -9
  655. package/dist/ui/assets/vendor-router-BtiNU7Dl.js +0 -3
  656. package/dist/utils/taskHierarchy.d.ts +0 -4
  657. package/dist/utils/taskHierarchy.js +0 -69
  658. package/dist/utils/taskHierarchy.test.js +0 -38
  659. package/dist/utils/taskParenting.d.ts +0 -3
  660. package/dist/utils/taskParenting.js +0 -24
  661. package/dist/utils/taskParenting.test.js +0 -21
  662. package/dist/utils/taskRelations.d.ts +0 -6
  663. package/dist/utils/taskRelations.js +0 -24
  664. package/dist/utils/taskRelations.test.js +0 -34
  665. package/scripts/check-compat-boundaries.js +0 -48
  666. /package/dist/{__tests__/planParser.test.d.ts → TaskforceCore.filter-persistence.test.d.ts} +0 -0
  667. /package/dist/{__tests__/releaseVersion.test.d.ts → TaskforceCore.routing.test.d.ts} +0 -0
  668. /package/dist/{__tests__/structuredCommentValidation.test.d.ts → annotatedAttachments/AnnotatedAttachmentSessionStore.test.d.ts} +0 -0
  669. /package/dist/{__tests__/structuredDocValidation.test.d.ts → annotatedAttachments/payload.test.d.ts} +0 -0
  670. /package/dist/{__tests__/templateEngine.test.d.ts → annotatedAttachments/types.js} +0 -0
  671. /package/dist/{__tests__/templates.test.d.ts → compat/workspaceSyncCompat.test.d.ts} +0 -0
  672. /package/dist/{__tests__/workflowDocumentFixtures.test.d.ts → components/features/AgentsModule.test.d.ts} +0 -0
  673. /package/dist/{__tests__/workflowExportMatrix.test.d.ts → components/features/AnnotatedAttachmentWorkspace.test.d.ts} +0 -0
  674. /package/dist/{__tests__/workflowExportSnapshots.test.d.ts → components/features/DocumentWorkspace.test.d.ts} +0 -0
  675. /package/dist/{__tests__/workflowGeneration.test.d.ts → components/features/settings/TaxonomyLibraryManager.test.d.ts} +0 -0
  676. /package/dist/{__tests__/workflowV2Policy.test.d.ts → components/task/TaskActionHeader.test.d.ts} +0 -0
  677. /package/dist/{core/InitiativeTemplates.test.d.ts → components/task/TaskKanban.planning-drop.test.d.ts} +0 -0
  678. /package/dist/{core/ParentLifecycle.test.d.ts → components/task/TaskStatusActions.test.d.ts} +0 -0
  679. /package/dist/{migrations/taskMigrations.test.d.ts → components/ui/TopNoticeLayer.test.d.ts} +0 -0
  680. /package/dist/{server/routes.billing.test.d.ts → components/views/AppShellHeader.test.d.ts} +0 -0
  681. /package/dist/{server/routes.sync.integration.test.d.ts → components/views/PlanComparisonPage.test.d.ts} +0 -0
  682. /package/dist/{utils/taskHierarchy.test.d.ts → components/views/chrome/WorkspaceChromeSections.test.d.ts} +0 -0
  683. /package/dist/{utils/taskParenting.test.d.ts → components/views/chrome/workspaceChrome.test.d.ts} +0 -0
  684. /package/dist/{utils/taskRelations.test.d.ts → components/views/panels/DocumentFilterToolbar.test.d.ts} +0 -0
  685. /package/dist/public/{android-chrome-192x192.png → archive/phoenix/android-chrome-192x192.png} +0 -0
  686. /package/dist/public/{android-chrome-512x512.png → archive/phoenix/android-chrome-512x512.png} +0 -0
  687. /package/dist/public/{favicon-16x16.png → archive/phoenix/favicon-16x16.png} +0 -0
  688. /package/dist/public/{favicon-32x32.png → archive/phoenix/favicon-32x32.png} +0 -0
  689. /package/dist/public/{favicon.png → archive/phoenix/favicon.png} +0 -0
  690. /package/dist/{__tests__ → services}/workflowExportSnapshots.test.js +0 -0
  691. /package/dist/{__tests__ → services}/workflowGeneration.test.js +0 -0
  692. /package/dist/ui/favicon/{android-chrome-192x192.png → archive/phoenix/android-chrome-192x192.png} +0 -0
  693. /package/dist/ui/favicon/{android-chrome-512x512.png → archive/phoenix/android-chrome-512x512.png} +0 -0
  694. /package/dist/ui/favicon/{favicon-16x16.png → archive/phoenix/favicon-16x16.png} +0 -0
  695. /package/dist/ui/favicon/{favicon-32x32.png → archive/phoenix/favicon-32x32.png} +0 -0
  696. /package/dist/ui/favicon/{favicon.png → archive/phoenix/favicon.png} +0 -0
@@ -1,991 +0,0 @@
1
- import Stripe from 'stripe';
2
- import { parseJsonBody } from './routes.js';
3
- const BILLING_CONFIG_KEY_PLAN = 'billing.config.v1';
4
- const PRICE_METADATA_PLAN_VERSION = 'taskforce_plan_version_id';
5
- const BILLING_DIAGNOSTIC_RETENTION_DAYS = 30;
6
- const BILLING_DIAGNOSTIC_MAX_PAYLOAD_BYTES = 8 * 1024;
7
- function isoFromUnixSeconds(raw) {
8
- const value = Number(raw);
9
- if (!Number.isFinite(value) || value <= 0)
10
- return null;
11
- return new Date(Math.floor(value) * 1000).toISOString();
12
- }
13
- function parseInterval(raw) {
14
- const value = String(raw || '').trim().toLowerCase();
15
- if (value === 'month' || value === 'year')
16
- return value;
17
- return null;
18
- }
19
- function resolveSubscriptionCurrentPeriodEnd(subscription) {
20
- const itemPeriods = Array.isArray(subscription.items?.data)
21
- ? subscription.items.data
22
- .map((item) => isoFromUnixSeconds(item?.current_period_end))
23
- .filter((value) => Boolean(value))
24
- : [];
25
- if (itemPeriods.length === 0)
26
- return null;
27
- return itemPeriods.sort()[itemPeriods.length - 1] || null;
28
- }
29
- function resolveInvoiceSubscriptionId(invoice) {
30
- const parentSubscription = String(invoice?.parent?.subscription_details?.subscription || '').trim();
31
- if (parentSubscription)
32
- return parentSubscription;
33
- const lineSubscription = String(invoice.lines?.data?.[0]?.subscription || '').trim();
34
- return lineSubscription;
35
- }
36
- function requestRuntimeMode(req) {
37
- const value = String(req.headers['x-taskforce-runtime-mode'] || '').trim().toLowerCase();
38
- return value === 'cloud' ? 'cloud' : 'local';
39
- }
40
- function parseBoolean(value, fallback = false) {
41
- const normalized = String(value ?? '').trim().toLowerCase();
42
- if (normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on')
43
- return true;
44
- if (normalized === 'false' || normalized === '0' || normalized === 'no' || normalized === 'off')
45
- return false;
46
- return fallback;
47
- }
48
- function parsePositiveIntBounded(raw, fallback, min, max) {
49
- const parsed = Number.parseInt(String(raw || '').trim(), 10);
50
- if (!Number.isFinite(parsed))
51
- return fallback;
52
- return Math.max(min, Math.min(max, parsed));
53
- }
54
- function resolveBaseUrl(req) {
55
- const host = String(req.headers['x-forwarded-host'] || req.headers.host || 'localhost').trim();
56
- const proto = String(req.headers['x-forwarded-proto'] || '').trim().toLowerCase() === 'http' ? 'http' : 'https';
57
- return `${proto}://${host.replace(/\/+$/, '')}`;
58
- }
59
- async function readRawBody(req, maxBytes = 1_048_576) {
60
- const chunks = [];
61
- let total = 0;
62
- for await (const chunk of req) {
63
- const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
64
- total += buf.length;
65
- if (total > maxBytes) {
66
- const error = new Error(`Payload too large (max ${maxBytes} bytes)`);
67
- error.statusCode = 413;
68
- throw error;
69
- }
70
- chunks.push(buf);
71
- }
72
- return Buffer.concat(chunks);
73
- }
74
- function mapStripeStatusToCanonicalState(statusRaw) {
75
- const status = String(statusRaw || '').trim().toLowerCase();
76
- if (status === 'trialing')
77
- return 'trialing';
78
- if (status === 'active')
79
- return 'active';
80
- if (status === 'past_due')
81
- return 'grace';
82
- return 'canceled';
83
- }
84
- function redactStripePayload(input) {
85
- const blockedKeys = new Set([
86
- 'billing_details',
87
- 'customer_details',
88
- 'payment_method',
89
- 'payment_method_details',
90
- 'payment_intent',
91
- 'charges',
92
- 'source',
93
- 'sources',
94
- 'card',
95
- 'default_source'
96
- ]);
97
- const visit = (value, depth) => {
98
- if (depth > 6)
99
- return '[truncated-depth]';
100
- if (value === null || value === undefined)
101
- return value;
102
- if (Array.isArray(value))
103
- return value.slice(0, 30).map((item) => visit(item, depth + 1));
104
- if (typeof value !== 'object')
105
- return value;
106
- const source = value;
107
- const out = {};
108
- for (const [key, child] of Object.entries(source)) {
109
- if (blockedKeys.has(key))
110
- continue;
111
- out[key] = visit(child, depth + 1);
112
- }
113
- return out;
114
- };
115
- const redacted = visit(input, 0);
116
- return redacted && typeof redacted === 'object' && !Array.isArray(redacted)
117
- ? redacted
118
- : {};
119
- }
120
- function boundedPayloadExcerpt(payload) {
121
- const raw = JSON.stringify(payload);
122
- if (Buffer.byteLength(raw, 'utf8') <= BILLING_DIAGNOSTIC_MAX_PAYLOAD_BYTES)
123
- return raw;
124
- const truncated = raw.slice(0, BILLING_DIAGNOSTIC_MAX_PAYLOAD_BYTES);
125
- return `${truncated}...[truncated]`;
126
- }
127
- function parseBillingConfig(raw) {
128
- const fallback = {
129
- trialDays: 30,
130
- tiers: {},
131
- taxEnabled: false,
132
- billingAddress: 'auto'
133
- };
134
- if (!raw || typeof raw !== 'object' || Array.isArray(raw))
135
- return fallback;
136
- const record = raw;
137
- const trialDaysRaw = Number(record.trial_days);
138
- const trialDays = Number.isFinite(trialDaysRaw) ? Math.max(1, Math.min(30, Math.floor(trialDaysRaw))) : 30;
139
- const billingAddress = String(record.billing_address || '').trim().toLowerCase() === 'required'
140
- ? 'required'
141
- : 'auto';
142
- return {
143
- trialDays,
144
- tiers: record.tiers && typeof record.tiers === 'object' && !Array.isArray(record.tiers)
145
- ? record.tiers
146
- : {},
147
- taxEnabled: parseBoolean(record.tax_enabled, false),
148
- billingAddress
149
- };
150
- }
151
- function billingDisabledResponse(res) {
152
- res.writeHead(403, { 'Content-Type': 'application/json' });
153
- res.end(JSON.stringify({ error: 'Billing is disabled.' }));
154
- }
155
- function cloudOnlyResponse(res) {
156
- res.writeHead(403, { 'Content-Type': 'application/json' });
157
- res.end(JSON.stringify({ error: 'Billing is only available in cloud runtime.' }));
158
- }
159
- function getStripeClient() {
160
- const key = String(process.env.TASKFORCE_STRIPE_SECRET_KEY || '').trim();
161
- if (!key) {
162
- const error = new Error('TASKFORCE_STRIPE_SECRET_KEY is not configured.');
163
- error.statusCode = 500;
164
- throw error;
165
- }
166
- return new Stripe(key);
167
- }
168
- function readBillingConfig(core) {
169
- const db = core.getDatabaseAdapter();
170
- const tenantId = core.getTenantId();
171
- const row = db.prepare(`
172
- SELECT payload
173
- FROM system_settings
174
- WHERE tenant_id = ? AND settings_key = ?
175
- LIMIT 1
176
- `).get(tenantId, BILLING_CONFIG_KEY_PLAN);
177
- if (!row?.payload)
178
- return parseBillingConfig({});
179
- try {
180
- return parseBillingConfig(JSON.parse(row.payload));
181
- }
182
- catch {
183
- return parseBillingConfig({});
184
- }
185
- }
186
- function writeBillingConfig(core, payload) {
187
- const db = core.getDatabaseAdapter();
188
- const tenantId = core.getTenantId();
189
- const now = new Date().toISOString();
190
- db.prepare(`
191
- INSERT INTO system_settings (tenant_id, settings_key, payload, updated_at)
192
- VALUES (?, ?, ?, ?)
193
- ON CONFLICT (tenant_id, settings_key) DO UPDATE SET
194
- payload = excluded.payload,
195
- updated_at = excluded.updated_at
196
- `).run(tenantId, BILLING_CONFIG_KEY_PLAN, JSON.stringify({
197
- trial_days: payload.trialDays,
198
- tiers: payload.tiers,
199
- tax_enabled: payload.taxEnabled,
200
- billing_address: payload.billingAddress
201
- }), now);
202
- }
203
- function resolveDefaultPlanVersionId(core, tierRaw) {
204
- const tier = String(tierRaw || '').trim().toLowerCase();
205
- if (!tier)
206
- return null;
207
- const db = core.getDatabaseAdapter();
208
- const tenantId = core.getTenantId();
209
- const row = db.prepare(`
210
- SELECT plan_version_id
211
- FROM plan_versions
212
- WHERE tenant_id = ? AND plan_id = ? AND is_default = 1
213
- LIMIT 1
214
- `).get(tenantId, tier);
215
- return row?.plan_version_id ? String(row.plan_version_id) : null;
216
- }
217
- function resolvePriceIdForPlanVersion(core, planVersionIdRaw, intervalRaw) {
218
- const planVersionId = String(planVersionIdRaw || '').trim();
219
- const interval = parseInterval(intervalRaw);
220
- if (!planVersionId || !interval)
221
- return null;
222
- const db = core.getDatabaseAdapter();
223
- const tenantId = core.getTenantId();
224
- const row = db.prepare(`
225
- SELECT stripe_price_id
226
- FROM billing_price_mappings
227
- WHERE tenant_id = ?
228
- AND plan_version_id = ?
229
- AND billing_interval = ?
230
- AND active = 1
231
- LIMIT 1
232
- `).get(tenantId, planVersionId, interval);
233
- return row?.stripe_price_id ? String(row.stripe_price_id) : null;
234
- }
235
- function resolvePlanVersionIdForPriceId(core, priceIdRaw) {
236
- const priceId = String(priceIdRaw || '').trim();
237
- if (!priceId)
238
- return null;
239
- const db = core.getDatabaseAdapter();
240
- const tenantId = core.getTenantId();
241
- const row = db.prepare(`
242
- SELECT plan_version_id
243
- FROM billing_price_mappings
244
- WHERE tenant_id = ?
245
- AND stripe_price_id = ?
246
- AND active = 1
247
- LIMIT 1
248
- `).get(tenantId, priceId);
249
- return row?.plan_version_id ? String(row.plan_version_id) : null;
250
- }
251
- function resolvePlanIdForVersion(core, planVersionIdRaw) {
252
- const planVersionId = String(planVersionIdRaw || '').trim();
253
- if (!planVersionId)
254
- return null;
255
- const db = core.getDatabaseAdapter();
256
- const tenantId = core.getTenantId();
257
- const row = db.prepare(`
258
- SELECT plan_id
259
- FROM plan_versions
260
- WHERE tenant_id = ? AND plan_version_id = ?
261
- LIMIT 1
262
- `).get(tenantId, planVersionId);
263
- return row?.plan_id ? String(row.plan_id) : null;
264
- }
265
- function getEntitlementRow(core, userIdRaw) {
266
- const userId = String(userIdRaw || '').trim();
267
- if (!userId)
268
- return null;
269
- const db = core.getDatabaseAdapter();
270
- const tenantId = core.getTenantId();
271
- const row = db.prepare(`
272
- SELECT account_id, plan_version_id, entitlement_state
273
- FROM account_entitlements
274
- WHERE tenant_id = ? AND account_id = ?
275
- LIMIT 1
276
- `).get(tenantId, userId);
277
- return row || null;
278
- }
279
- function upsertCanonicalEntitlement(core, input) {
280
- const db = core.getDatabaseAdapter();
281
- const tenantId = core.getTenantId();
282
- const now = new Date().toISOString();
283
- db.prepare(`
284
- INSERT INTO account_entitlements (account_id, tenant_id, plan_version_id, entitlement_state, effective_at, effective_until, updated_by, created_at, updated_at)
285
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
286
- ON CONFLICT (account_id) DO UPDATE SET
287
- plan_version_id = excluded.plan_version_id,
288
- entitlement_state = excluded.entitlement_state,
289
- effective_at = excluded.effective_at,
290
- effective_until = excluded.effective_until,
291
- updated_by = excluded.updated_by,
292
- updated_at = excluded.updated_at
293
- `).run(input.userId, tenantId, input.planVersionId, input.state, input.effectiveAt || now, input.effectiveUntil || null, input.updatedBy || 'stripe-webhook', now, now);
294
- }
295
- function upsertBillingMirror(core, input) {
296
- const db = core.getDatabaseAdapter();
297
- const tenantId = core.getTenantId();
298
- const now = new Date().toISOString();
299
- const existingRow = db.prepare(`
300
- SELECT tier
301
- FROM user_billing
302
- WHERE tenant_id = ? AND user_id = ?
303
- LIMIT 1
304
- `).get(tenantId, input.userId);
305
- const resolvedTier = String(input.planId || existingRow?.tier || 'free').trim() || 'free';
306
- db.prepare(`
307
- INSERT INTO user_billing (
308
- user_id, tenant_id, stripe_customer_id, stripe_subscription_id, stripe_price_id, stripe_status, tier, billing_interval,
309
- entitlement_state, trial_end, current_period_end, effective_until, created_at, updated_at
310
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
311
- ON CONFLICT (user_id) DO UPDATE SET
312
- stripe_customer_id = COALESCE(excluded.stripe_customer_id, user_billing.stripe_customer_id),
313
- stripe_subscription_id = COALESCE(excluded.stripe_subscription_id, user_billing.stripe_subscription_id),
314
- stripe_price_id = COALESCE(excluded.stripe_price_id, user_billing.stripe_price_id),
315
- stripe_status = COALESCE(excluded.stripe_status, user_billing.stripe_status),
316
- tier = COALESCE(excluded.tier, user_billing.tier),
317
- billing_interval = COALESCE(excluded.billing_interval, user_billing.billing_interval),
318
- entitlement_state = COALESCE(excluded.entitlement_state, user_billing.entitlement_state),
319
- trial_end = COALESCE(excluded.trial_end, user_billing.trial_end),
320
- current_period_end = COALESCE(excluded.current_period_end, user_billing.current_period_end),
321
- effective_until = COALESCE(excluded.effective_until, user_billing.effective_until),
322
- updated_at = excluded.updated_at
323
- `).run(input.userId, tenantId, input.stripeCustomerId || null, input.stripeSubscriptionId || null, input.stripePriceId || null, input.stripeStatus || null, resolvedTier, input.billingInterval || null, input.canonicalState || null, input.trialEnd || null, input.currentPeriodEnd || null, input.effectiveUntil || null, now, now);
324
- }
325
- function resolveUserIdByCustomer(core, customerIdRaw) {
326
- const customerId = String(customerIdRaw || '').trim();
327
- if (!customerId)
328
- return null;
329
- const db = core.getDatabaseAdapter();
330
- const tenantId = core.getTenantId();
331
- const row = db.prepare(`
332
- SELECT user_id
333
- FROM user_billing
334
- WHERE tenant_id = ? AND stripe_customer_id = ?
335
- LIMIT 1
336
- `).get(tenantId, customerId);
337
- return row?.user_id ? String(row.user_id) : null;
338
- }
339
- function resolveUserIdBySubscription(core, subscriptionIdRaw) {
340
- const subscriptionId = String(subscriptionIdRaw || '').trim();
341
- if (!subscriptionId)
342
- return null;
343
- const db = core.getDatabaseAdapter();
344
- const tenantId = core.getTenantId();
345
- const row = db.prepare(`
346
- SELECT user_id
347
- FROM user_billing
348
- WHERE tenant_id = ? AND stripe_subscription_id = ?
349
- LIMIT 1
350
- `).get(tenantId, subscriptionId);
351
- return row?.user_id ? String(row.user_id) : null;
352
- }
353
- function purgeExpiredWebhookFailures(core) {
354
- const db = core.getDatabaseAdapter();
355
- const tenantId = core.getTenantId();
356
- const result = db.prepare(`
357
- DELETE FROM stripe_webhook_failures
358
- WHERE tenant_id = ?
359
- AND purge_after < ?
360
- `).run(tenantId, new Date().toISOString());
361
- return Number(result?.changes || 0);
362
- }
363
- function recordWebhookFailure(core, input) {
364
- try {
365
- const db = core.getDatabaseAdapter();
366
- const tenantId = core.getTenantId();
367
- const now = new Date();
368
- const purgeAfter = new Date(now.getTime() + BILLING_DIAGNOSTIC_RETENTION_DAYS * 24 * 60 * 60 * 1000).toISOString();
369
- const redacted = redactStripePayload(input.payload);
370
- const excerpt = boundedPayloadExcerpt(redacted);
371
- const id = `whf-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
372
- db.prepare(`
373
- INSERT INTO stripe_webhook_failures (id, tenant_id, event_id, event_type, reason, payload_excerpt, purge_after, created_at)
374
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
375
- `).run(id, tenantId, input.eventId, input.eventType, input.reason, excerpt, purgeAfter, now.toISOString());
376
- }
377
- catch {
378
- // diagnostics are best-effort only
379
- }
380
- }
381
- function resolvePriceAndIntervalFromInvoice(invoice) {
382
- const line = invoice.lines?.data?.find((entry) => !!entry?.price?.id || !!entry?.pricing?.price_details?.price);
383
- const legacyPriceId = String(line?.price?.id || '').trim();
384
- const modernPriceId = String(line?.pricing?.price_details?.price || '').trim();
385
- const priceId = modernPriceId || legacyPriceId || null;
386
- const recurringInterval = parseInterval(line?.price?.recurring?.interval || '');
387
- return { priceId, interval: recurringInterval };
388
- }
389
- function lockWebhookEvent(core, event) {
390
- const db = core.getDatabaseAdapter();
391
- const tenantId = core.getTenantId();
392
- const result = db.prepare(`
393
- INSERT INTO stripe_webhook_events (event_id, tenant_id, event_type, processed_at)
394
- VALUES (?, ?, ?, ?)
395
- ON CONFLICT (event_id) DO NOTHING
396
- `).run(event.id, tenantId, event.type, new Date().toISOString());
397
- return Number(result?.changes || 0) > 0;
398
- }
399
- async function importStripePrices(core) {
400
- const stripe = getStripeClient();
401
- const db = core.getDatabaseAdapter();
402
- const tenantId = core.getTenantId();
403
- const now = new Date().toISOString();
404
- const validPlanVersionIds = new Set(db.prepare(`
405
- SELECT plan_version_id
406
- FROM plan_versions
407
- WHERE tenant_id = ?
408
- `).all(tenantId).map((row) => String(row.plan_version_id || '')).filter(Boolean));
409
- const importedPriceIds = new Set();
410
- const summary = {
411
- imported: 0,
412
- skipped: 0,
413
- deactivated: 0,
414
- details: []
415
- };
416
- let startingAfter;
417
- while (true) {
418
- const page = await stripe.prices.list({
419
- active: true,
420
- limit: 100,
421
- starting_after: startingAfter,
422
- type: 'recurring'
423
- });
424
- for (const price of page.data) {
425
- const interval = parseInterval(price.recurring?.interval || '');
426
- const planVersionId = String(price.metadata?.[PRICE_METADATA_PLAN_VERSION] || '').trim();
427
- if (!interval || !planVersionId || !validPlanVersionIds.has(planVersionId)) {
428
- summary.skipped += 1;
429
- summary.details.push({
430
- priceId: price.id,
431
- status: 'skipped',
432
- reason: !planVersionId
433
- ? `Missing metadata ${PRICE_METADATA_PLAN_VERSION}`
434
- : (!interval ? 'Unsupported interval' : 'Unknown plan_version_id')
435
- });
436
- continue;
437
- }
438
- db.prepare(`
439
- INSERT INTO billing_price_mappings (
440
- tenant_id, plan_version_id, billing_interval, stripe_price_id, active, created_at, updated_at
441
- ) VALUES (?, ?, ?, ?, 1, ?, ?)
442
- ON CONFLICT (tenant_id, stripe_price_id) DO UPDATE SET
443
- plan_version_id = excluded.plan_version_id,
444
- billing_interval = excluded.billing_interval,
445
- active = 1,
446
- updated_at = excluded.updated_at
447
- `).run(tenantId, planVersionId, interval, price.id, now, now);
448
- importedPriceIds.add(price.id);
449
- summary.imported += 1;
450
- summary.details.push({ priceId: price.id, status: 'imported' });
451
- }
452
- if (!page.has_more || page.data.length === 0)
453
- break;
454
- startingAfter = page.data[page.data.length - 1]?.id;
455
- if (!startingAfter)
456
- break;
457
- }
458
- const existing = db.prepare(`
459
- SELECT stripe_price_id
460
- FROM billing_price_mappings
461
- WHERE tenant_id = ? AND active = 1
462
- `).all(tenantId);
463
- for (const row of existing) {
464
- const priceId = String(row.stripe_price_id || '').trim();
465
- if (!priceId || importedPriceIds.has(priceId))
466
- continue;
467
- db.prepare(`
468
- UPDATE billing_price_mappings
469
- SET active = 0, updated_at = ?
470
- WHERE tenant_id = ? AND stripe_price_id = ?
471
- `).run(now, tenantId, priceId);
472
- summary.deactivated += 1;
473
- }
474
- return summary;
475
- }
476
- export function registerBillingRoutes(deps) {
477
- const { addRoute, core, context, ensureAuthenticatedUser, ensureAdminRole, requestUserId, resolveErrorStatusCode, auditAdminAction } = deps;
478
- const billingEnabled = () => parseBoolean(process.env.TASKFORCE_BILLING_ENABLED, false);
479
- const ensureCloudBilling = (req, res) => {
480
- if (!billingEnabled()) {
481
- billingDisabledResponse(res);
482
- return false;
483
- }
484
- const runtime = context.authConfig?.runtimeMode || requestRuntimeMode(req);
485
- if (runtime !== 'cloud') {
486
- cloudOnlyResponse(res);
487
- return false;
488
- }
489
- return true;
490
- };
491
- addRoute('GET', '/api/taskforce/billing/status', async (req, res) => {
492
- if (!ensureCloudBilling(req, res))
493
- return;
494
- if (!ensureAuthenticatedUser(req)) {
495
- res.writeHead(401, { 'Content-Type': 'application/json' });
496
- res.end(JSON.stringify({ error: 'Authentication required.' }));
497
- return;
498
- }
499
- try {
500
- const userId = requestUserId(req);
501
- const entitlement = core.getAccountEntitlement(userId);
502
- const db = core.getDatabaseAdapter();
503
- const tenantId = core.getTenantId();
504
- const row = db.prepare(`
505
- SELECT stripe_status, stripe_customer_id, stripe_subscription_id, stripe_price_id, billing_interval, trial_end, current_period_end, effective_until
506
- FROM user_billing
507
- WHERE tenant_id = ? AND user_id = ?
508
- LIMIT 1
509
- `).get(tenantId, userId);
510
- res.writeHead(200, { 'Content-Type': 'application/json' });
511
- res.end(JSON.stringify({
512
- stripeStatus: row?.stripe_status || null,
513
- stripeCustomerId: row?.stripe_customer_id || null,
514
- stripeSubscriptionId: row?.stripe_subscription_id || null,
515
- stripePriceId: row?.stripe_price_id || null,
516
- billingInterval: row?.billing_interval || null,
517
- trialEnd: row?.trial_end || null,
518
- currentPeriodEnd: row?.current_period_end || null,
519
- effectiveUntil: row?.effective_until || null,
520
- entitlementState: entitlement.state,
521
- planVersionId: entitlement.planVersionId,
522
- planId: entitlement.planId
523
- }));
524
- }
525
- catch (error) {
526
- const statusCode = resolveErrorStatusCode(error, 400);
527
- res.writeHead(statusCode, { 'Content-Type': 'application/json' });
528
- res.end(JSON.stringify({ error: String(error?.message || 'Unable to read billing status'), code: error?.code }));
529
- }
530
- });
531
- addRoute('GET', '/api/taskforce/admin/billing/config', async (req, res) => {
532
- if (!ensureCloudBilling(req, res))
533
- return;
534
- if (!ensureAdminRole(req)) {
535
- res.writeHead(403, { 'Content-Type': 'application/json' });
536
- res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
537
- return;
538
- }
539
- const config = readBillingConfig(core);
540
- res.writeHead(200, { 'Content-Type': 'application/json' });
541
- res.end(JSON.stringify(config));
542
- });
543
- addRoute('PUT', '/api/taskforce/admin/billing/config', async (req, res) => {
544
- if (!ensureCloudBilling(req, res))
545
- return;
546
- if (!ensureAdminRole(req)) {
547
- res.writeHead(403, { 'Content-Type': 'application/json' });
548
- res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
549
- return;
550
- }
551
- const body = await parseJsonBody(req);
552
- const trialDaysRaw = Number(body?.trial_days);
553
- if (!Number.isFinite(trialDaysRaw) || trialDaysRaw < 1 || trialDaysRaw > 30) {
554
- res.writeHead(400, { 'Content-Type': 'application/json' });
555
- res.end(JSON.stringify({ error: 'trial_days must be an integer between 1 and 30.' }));
556
- return;
557
- }
558
- const nextConfig = {
559
- trialDays: Math.floor(trialDaysRaw),
560
- tiers: body?.tiers && typeof body.tiers === 'object' && !Array.isArray(body.tiers) ? body.tiers : {},
561
- taxEnabled: parseBoolean(body?.tax_enabled, false),
562
- billingAddress: String(body?.billing_address || '').trim().toLowerCase() === 'required' ? 'required' : 'auto'
563
- };
564
- writeBillingConfig(core, nextConfig);
565
- auditAdminAction(req, 'billing-config-updated', { trialDays: nextConfig.trialDays, billingAddress: nextConfig.billingAddress });
566
- res.writeHead(200, { 'Content-Type': 'application/json' });
567
- res.end(JSON.stringify(nextConfig));
568
- });
569
- addRoute('GET', '/api/taskforce/admin/billing/prices', async (req, res) => {
570
- if (!ensureCloudBilling(req, res))
571
- return;
572
- if (!ensureAdminRole(req)) {
573
- res.writeHead(403, { 'Content-Type': 'application/json' });
574
- res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
575
- return;
576
- }
577
- const db = core.getDatabaseAdapter();
578
- const tenantId = core.getTenantId();
579
- const rows = db.prepare(`
580
- SELECT plan_version_id, billing_interval, stripe_price_id, active, created_at, updated_at
581
- FROM billing_price_mappings
582
- WHERE tenant_id = ?
583
- ORDER BY plan_version_id ASC, billing_interval ASC, stripe_price_id ASC
584
- `).all(tenantId);
585
- res.writeHead(200, { 'Content-Type': 'application/json' });
586
- res.end(JSON.stringify({ prices: rows }));
587
- });
588
- addRoute('GET', '/api/taskforce/admin/billing/webhook-failures', async (req, res) => {
589
- if (!ensureCloudBilling(req, res))
590
- return;
591
- if (!ensureAdminRole(req)) {
592
- res.writeHead(403, { 'Content-Type': 'application/json' });
593
- res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
594
- return;
595
- }
596
- const db = core.getDatabaseAdapter();
597
- const tenantId = core.getTenantId();
598
- const queryLimit = req.url
599
- ? new URL(req.url, 'https://taskforce.local').searchParams.get('limit')
600
- : null;
601
- const limit = parsePositiveIntBounded(queryLimit, 50, 1, 200);
602
- const now = new Date().toISOString();
603
- const purged = purgeExpiredWebhookFailures(core);
604
- const rows = db.prepare(`
605
- SELECT id, event_id, event_type, reason, payload_excerpt, created_at, purge_after
606
- FROM stripe_webhook_failures
607
- WHERE tenant_id = ?
608
- ORDER BY created_at DESC
609
- LIMIT ?
610
- `).all(tenantId, limit);
611
- const total = db.prepare(`
612
- SELECT COUNT(*) AS count
613
- FROM stripe_webhook_failures
614
- WHERE tenant_id = ?
615
- `).get(tenantId);
616
- const expiringSoon = db.prepare(`
617
- SELECT COUNT(*) AS count
618
- FROM stripe_webhook_failures
619
- WHERE tenant_id = ?
620
- AND purge_after <= ?
621
- `).get(tenantId, new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString());
622
- res.writeHead(200, { 'Content-Type': 'application/json' });
623
- res.end(JSON.stringify({
624
- asOf: now,
625
- purgedExpiredRows: purged,
626
- total: Number(total?.count || 0),
627
- expiringWithin24h: Number(expiringSoon?.count || 0),
628
- rows
629
- }));
630
- });
631
- addRoute('POST', '/api/taskforce/admin/billing/prices/import', async (req, res) => {
632
- if (!ensureCloudBilling(req, res))
633
- return;
634
- if (!ensureAdminRole(req)) {
635
- res.writeHead(403, { 'Content-Type': 'application/json' });
636
- res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
637
- return;
638
- }
639
- try {
640
- const summary = await importStripePrices(core);
641
- auditAdminAction(req, 'billing-prices-import', {
642
- imported: summary.imported,
643
- skipped: summary.skipped,
644
- deactivated: summary.deactivated
645
- });
646
- res.writeHead(200, { 'Content-Type': 'application/json' });
647
- res.end(JSON.stringify(summary));
648
- }
649
- catch (error) {
650
- const statusCode = resolveErrorStatusCode(error, 400);
651
- res.writeHead(statusCode, { 'Content-Type': 'application/json' });
652
- res.end(JSON.stringify({ error: String(error?.message || 'Unable to import Stripe prices'), code: error?.code }));
653
- }
654
- });
655
- addRoute('POST', '/api/taskforce/billing/checkout-session', async (req, res) => {
656
- if (!ensureCloudBilling(req, res))
657
- return;
658
- if (!ensureAuthenticatedUser(req)) {
659
- res.writeHead(401, { 'Content-Type': 'application/json' });
660
- res.end(JSON.stringify({ error: 'Authentication required.' }));
661
- return;
662
- }
663
- const body = await parseJsonBody(req);
664
- const interval = parseInterval(body?.interval);
665
- const planVersionId = String(body?.planVersionId || '').trim() || resolveDefaultPlanVersionId(core, body?.tier);
666
- if (!interval || !planVersionId) {
667
- res.writeHead(400, { 'Content-Type': 'application/json' });
668
- res.end(JSON.stringify({ error: 'planVersionId (or tier) and interval are required.' }));
669
- return;
670
- }
671
- const priceId = resolvePriceIdForPlanVersion(core, planVersionId, interval);
672
- if (!priceId) {
673
- res.writeHead(400, { 'Content-Type': 'application/json' });
674
- res.end(JSON.stringify({ error: 'No active Stripe price mapping found for requested plan/interval.' }));
675
- return;
676
- }
677
- try {
678
- const stripe = getStripeClient();
679
- const userId = requestUserId(req);
680
- const baseUrl = resolveBaseUrl(req);
681
- const config = readBillingConfig(core);
682
- const session = await stripe.checkout.sessions.create({
683
- mode: 'subscription',
684
- line_items: [{ price: priceId, quantity: 1 }],
685
- success_url: `${baseUrl}/billing/success?session_id={CHECKOUT_SESSION_ID}`,
686
- cancel_url: `${baseUrl}/billing/cancel`,
687
- subscription_data: {
688
- trial_period_days: config.trialDays
689
- },
690
- billing_address_collection: config.billingAddress,
691
- automatic_tax: { enabled: config.taxEnabled },
692
- customer_creation: 'always',
693
- client_reference_id: userId,
694
- metadata: {
695
- userId,
696
- tenantId: core.getTenantId(),
697
- planVersionId
698
- }
699
- });
700
- res.writeHead(200, { 'Content-Type': 'application/json' });
701
- res.end(JSON.stringify({ url: session.url || null, id: session.id }));
702
- }
703
- catch (error) {
704
- const statusCode = resolveErrorStatusCode(error, 400);
705
- res.writeHead(statusCode, { 'Content-Type': 'application/json' });
706
- res.end(JSON.stringify({ error: String(error?.message || 'Unable to create checkout session'), code: error?.code }));
707
- }
708
- });
709
- addRoute('POST', '/api/taskforce/billing/portal-session', async (req, res) => {
710
- if (!ensureCloudBilling(req, res))
711
- return;
712
- if (!ensureAuthenticatedUser(req)) {
713
- res.writeHead(401, { 'Content-Type': 'application/json' });
714
- res.end(JSON.stringify({ error: 'Authentication required.' }));
715
- return;
716
- }
717
- const userId = requestUserId(req);
718
- const db = core.getDatabaseAdapter();
719
- const tenantId = core.getTenantId();
720
- const row = db.prepare(`
721
- SELECT stripe_customer_id
722
- FROM user_billing
723
- WHERE tenant_id = ? AND user_id = ?
724
- LIMIT 1
725
- `).get(tenantId, userId);
726
- const customerId = String(row?.stripe_customer_id || '').trim();
727
- if (!customerId) {
728
- res.writeHead(400, { 'Content-Type': 'application/json' });
729
- res.end(JSON.stringify({ error: 'No Stripe customer is linked for this account.' }));
730
- return;
731
- }
732
- try {
733
- const stripe = getStripeClient();
734
- const baseUrl = resolveBaseUrl(req);
735
- const session = await stripe.billingPortal.sessions.create({
736
- customer: customerId,
737
- return_url: `${baseUrl}/settings`
738
- });
739
- res.writeHead(200, { 'Content-Type': 'application/json' });
740
- res.end(JSON.stringify({ url: session.url }));
741
- }
742
- catch (error) {
743
- const statusCode = resolveErrorStatusCode(error, 400);
744
- res.writeHead(statusCode, { 'Content-Type': 'application/json' });
745
- res.end(JSON.stringify({ error: String(error?.message || 'Unable to create portal session'), code: error?.code }));
746
- }
747
- });
748
- addRoute('POST', '/api/taskforce/billing/subscription', async (req, res) => {
749
- if (!ensureCloudBilling(req, res))
750
- return;
751
- if (!ensureAuthenticatedUser(req)) {
752
- res.writeHead(401, { 'Content-Type': 'application/json' });
753
- res.end(JSON.stringify({ error: 'Authentication required.' }));
754
- return;
755
- }
756
- const body = await parseJsonBody(req);
757
- const interval = parseInterval(body?.interval);
758
- const planVersionId = String(body?.planVersionId || '').trim() || resolveDefaultPlanVersionId(core, body?.tier);
759
- if (!interval || !planVersionId) {
760
- res.writeHead(400, { 'Content-Type': 'application/json' });
761
- res.end(JSON.stringify({ error: 'planVersionId (or tier) and interval are required.' }));
762
- return;
763
- }
764
- const nextPriceId = resolvePriceIdForPlanVersion(core, planVersionId, interval);
765
- if (!nextPriceId) {
766
- res.writeHead(400, { 'Content-Type': 'application/json' });
767
- res.end(JSON.stringify({ error: 'No active Stripe price mapping found for requested plan/interval.' }));
768
- return;
769
- }
770
- const userId = requestUserId(req);
771
- const db = core.getDatabaseAdapter();
772
- const tenantId = core.getTenantId();
773
- const row = db.prepare(`
774
- SELECT stripe_subscription_id
775
- FROM user_billing
776
- WHERE tenant_id = ? AND user_id = ?
777
- LIMIT 1
778
- `).get(tenantId, userId);
779
- const subscriptionId = String(row?.stripe_subscription_id || '').trim();
780
- if (!subscriptionId) {
781
- res.writeHead(400, { 'Content-Type': 'application/json' });
782
- res.end(JSON.stringify({ error: 'No Stripe subscription is linked for this account.' }));
783
- return;
784
- }
785
- try {
786
- const stripe = getStripeClient();
787
- const current = await stripe.subscriptions.retrieve(subscriptionId);
788
- const itemId = current.items.data[0]?.id;
789
- if (!itemId) {
790
- res.writeHead(400, { 'Content-Type': 'application/json' });
791
- res.end(JSON.stringify({ error: 'Subscription has no updatable line item.' }));
792
- return;
793
- }
794
- const updated = await stripe.subscriptions.update(subscriptionId, {
795
- items: [{ id: itemId, price: nextPriceId }],
796
- proration_behavior: 'create_prorations',
797
- metadata: {
798
- planVersionId
799
- }
800
- });
801
- res.writeHead(200, { 'Content-Type': 'application/json' });
802
- res.end(JSON.stringify({ subscription: updated }));
803
- }
804
- catch (error) {
805
- const statusCode = resolveErrorStatusCode(error, 400);
806
- res.writeHead(statusCode, { 'Content-Type': 'application/json' });
807
- res.end(JSON.stringify({ error: String(error?.message || 'Unable to update subscription'), code: error?.code }));
808
- }
809
- });
810
- addRoute('POST', '/api/taskforce/billing/webhook', async (req, res) => {
811
- if (!ensureCloudBilling(req, res))
812
- return;
813
- const webhookSecret = String(process.env.TASKFORCE_STRIPE_WEBHOOK_SECRET || '').trim();
814
- if (!webhookSecret) {
815
- res.writeHead(500, { 'Content-Type': 'application/json' });
816
- res.end(JSON.stringify({ error: 'TASKFORCE_STRIPE_WEBHOOK_SECRET is not configured.' }));
817
- return;
818
- }
819
- const signature = String(req.headers['stripe-signature'] || '').trim();
820
- if (!signature) {
821
- res.writeHead(400, { 'Content-Type': 'application/json' });
822
- res.end(JSON.stringify({ error: 'Missing Stripe signature.' }));
823
- return;
824
- }
825
- let event;
826
- let rawBody;
827
- try {
828
- rawBody = await readRawBody(req);
829
- const stripe = getStripeClient();
830
- event = stripe.webhooks.constructEvent(rawBody, signature, webhookSecret);
831
- }
832
- catch (error) {
833
- const code = Number(error?.statusCode || 400);
834
- res.writeHead(code >= 400 && code < 600 ? code : 400, { 'Content-Type': 'application/json' });
835
- res.end(JSON.stringify({ error: String(error?.message || 'Invalid webhook payload/signature') }));
836
- return;
837
- }
838
- try {
839
- const db = core.getDatabaseAdapter();
840
- const tenantId = core.getTenantId();
841
- purgeExpiredWebhookFailures(core);
842
- let duplicate = false;
843
- const tx = db.transaction(() => {
844
- const acquired = lockWebhookEvent(core, event);
845
- if (!acquired) {
846
- duplicate = true;
847
- return;
848
- }
849
- if (event.type === 'checkout.session.completed') {
850
- const session = event.data.object;
851
- const metadata = session.metadata || {};
852
- const customerId = String(session.customer || '').trim();
853
- const subscriptionId = String(session.subscription || '').trim();
854
- const userId = String(metadata.userId || metadata.user_id || '').trim()
855
- || resolveUserIdByCustomer(core, customerId)
856
- || resolveUserIdBySubscription(core, subscriptionId);
857
- if (!userId || !customerId) {
858
- throw new Error('Unable to link checkout completion to user/customer.');
859
- }
860
- core.createUserBillingRecord(userId);
861
- upsertBillingMirror(core, {
862
- userId,
863
- stripeCustomerId: customerId,
864
- stripeSubscriptionId: subscriptionId || null
865
- });
866
- return;
867
- }
868
- if (event.type === 'customer.subscription.created' || event.type === 'customer.subscription.updated' || event.type === 'customer.subscription.deleted') {
869
- const subscription = event.data.object;
870
- const customerId = String(subscription.customer || '').trim();
871
- const userId = resolveUserIdByCustomer(core, customerId)
872
- || String(subscription.metadata?.userId || subscription.metadata?.user_id || '').trim();
873
- if (!userId) {
874
- throw new Error('Unable to resolve user for subscription event.');
875
- }
876
- core.createUserBillingRecord(userId);
877
- const stripeStatus = String(subscription.status || '').trim().toLowerCase();
878
- const priceId = String(subscription.items?.data?.[0]?.price?.id || '').trim();
879
- const billingInterval = parseInterval(subscription.items?.data?.[0]?.price?.recurring?.interval || '');
880
- const planVersionId = resolvePlanVersionIdForPriceId(core, priceId);
881
- const existingEntitlement = getEntitlementRow(core, userId);
882
- const nowIso = new Date().toISOString();
883
- const currentPeriodEnd = resolveSubscriptionCurrentPeriodEnd(subscription);
884
- const trialEnd = isoFromUnixSeconds(subscription.trial_end);
885
- const canceledState = stripeStatus === 'canceled'
886
- ? (currentPeriodEnd && currentPeriodEnd > nowIso ? 'active' : 'canceled')
887
- : null;
888
- const canonicalState = canceledState || mapStripeStatusToCanonicalState(stripeStatus);
889
- const effectiveUntil = stripeStatus === 'canceled'
890
- ? currentPeriodEnd
891
- : (currentPeriodEnd || null);
892
- upsertBillingMirror(core, {
893
- userId,
894
- stripeCustomerId: customerId || null,
895
- stripeSubscriptionId: String(subscription.id || '').trim() || null,
896
- stripePriceId: priceId || null,
897
- stripeStatus: stripeStatus || null,
898
- planId: planVersionId ? resolvePlanIdForVersion(core, planVersionId) : null,
899
- billingInterval: billingInterval || null,
900
- canonicalState,
901
- trialEnd,
902
- currentPeriodEnd,
903
- effectiveUntil
904
- });
905
- if (!planVersionId) {
906
- recordWebhookFailure(core, {
907
- eventId: event.id,
908
- eventType: event.type,
909
- reason: `Unknown price mapping for price_id=${priceId || '(empty)'}`,
910
- payload: event
911
- });
912
- return;
913
- }
914
- upsertCanonicalEntitlement(core, {
915
- userId,
916
- planVersionId: planVersionId || existingEntitlement?.plan_version_id || 'free-v1',
917
- state: canonicalState,
918
- effectiveAt: trialEnd || nowIso,
919
- effectiveUntil
920
- });
921
- return;
922
- }
923
- if (event.type === 'invoice.paid' || event.type === 'invoice.payment_failed') {
924
- const invoice = event.data.object;
925
- const customerId = String(invoice.customer || '').trim();
926
- const subscriptionId = resolveInvoiceSubscriptionId(invoice);
927
- const userId = resolveUserIdByCustomer(core, customerId)
928
- || resolveUserIdBySubscription(core, subscriptionId);
929
- if (!userId) {
930
- throw new Error('Unable to resolve user for invoice event.');
931
- }
932
- core.createUserBillingRecord(userId);
933
- const { priceId, interval } = resolvePriceAndIntervalFromInvoice(invoice);
934
- const planVersionId = resolvePlanVersionIdForPriceId(core, priceId);
935
- const existingEntitlement = getEntitlementRow(core, userId);
936
- const canonicalState = event.type === 'invoice.payment_failed' ? 'grace' : 'active';
937
- const currentPeriodEnd = invoice.lines?.data?.[0]?.period?.end
938
- ? isoFromUnixSeconds(invoice.lines.data[0].period.end)
939
- : null;
940
- upsertBillingMirror(core, {
941
- userId,
942
- stripeCustomerId: customerId || null,
943
- stripeSubscriptionId: subscriptionId || null,
944
- stripePriceId: priceId || null,
945
- stripeStatus: event.type === 'invoice.payment_failed' ? 'past_due' : 'active',
946
- planId: planVersionId ? resolvePlanIdForVersion(core, planVersionId) : null,
947
- billingInterval: interval || null,
948
- canonicalState,
949
- currentPeriodEnd,
950
- effectiveUntil: currentPeriodEnd
951
- });
952
- if (!planVersionId) {
953
- recordWebhookFailure(core, {
954
- eventId: event.id,
955
- eventType: event.type,
956
- reason: `Unknown price mapping for price_id=${priceId || '(empty)'}`,
957
- payload: event
958
- });
959
- return;
960
- }
961
- upsertCanonicalEntitlement(core, {
962
- userId,
963
- planVersionId: planVersionId || existingEntitlement?.plan_version_id || 'free-v1',
964
- state: canonicalState,
965
- effectiveAt: new Date().toISOString(),
966
- effectiveUntil: currentPeriodEnd
967
- });
968
- return;
969
- }
970
- });
971
- tx();
972
- if (duplicate) {
973
- res.writeHead(200, { 'Content-Type': 'application/json' });
974
- res.end(JSON.stringify({ received: true, duplicate: true }));
975
- return;
976
- }
977
- res.writeHead(200, { 'Content-Type': 'application/json' });
978
- res.end(JSON.stringify({ received: true }));
979
- }
980
- catch (error) {
981
- recordWebhookFailure(core, {
982
- eventId: event.id,
983
- eventType: event.type,
984
- reason: String(error?.message || error || 'WEBHOOK_PROCESSING_FAILED'),
985
- payload: event
986
- });
987
- res.writeHead(500, { 'Content-Type': 'application/json' });
988
- res.end(JSON.stringify({ error: 'Webhook processing failed. Retry expected.' }));
989
- }
990
- });
991
- }