@taskforcehq/taskforce 0.3.168

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 (492) hide show
  1. package/README.md +241 -0
  2. package/dist/Taskforce.d.ts +3 -0
  3. package/dist/Taskforce.js +3 -0
  4. package/dist/Taskforce.module.css +7587 -0
  5. package/dist/TaskforceCore.CategoryFallback.test.d.ts +1 -0
  6. package/dist/TaskforceCore.CategoryFallback.test.js +98 -0
  7. package/dist/TaskforceCore.d.ts +12 -0
  8. package/dist/TaskforceCore.js +729 -0
  9. package/dist/TaskforceCore.test.d.ts +1 -0
  10. package/dist/TaskforceCore.test.js +2132 -0
  11. package/dist/TaskforceScreenshot.d.ts +11 -0
  12. package/dist/TaskforceScreenshot.js +113 -0
  13. package/dist/TaskforceWidget.d.ts +6 -0
  14. package/dist/TaskforceWidget.js +101 -0
  15. package/dist/TaskforceWidget.test.d.ts +1 -0
  16. package/dist/TaskforceWidget.test.js +92 -0
  17. package/dist/UnsavedChangesRelaxed.test.d.ts +1 -0
  18. package/dist/UnsavedChangesRelaxed.test.js +16 -0
  19. package/dist/__tests__/localizationCatalogs.test.d.ts +1 -0
  20. package/dist/__tests__/localizationCatalogs.test.js +37 -0
  21. package/dist/__tests__/planParser.test.d.ts +1 -0
  22. package/dist/__tests__/planParser.test.js +183 -0
  23. package/dist/__tests__/releaseVersion.test.d.ts +1 -0
  24. package/dist/__tests__/releaseVersion.test.js +32 -0
  25. package/dist/__tests__/structuredCommentValidation.test.d.ts +1 -0
  26. package/dist/__tests__/structuredCommentValidation.test.js +31 -0
  27. package/dist/__tests__/structuredDocValidation.test.d.ts +1 -0
  28. package/dist/__tests__/structuredDocValidation.test.js +30 -0
  29. package/dist/__tests__/templateEngine.test.d.ts +1 -0
  30. package/dist/__tests__/templateEngine.test.js +150 -0
  31. package/dist/__tests__/templates.test.d.ts +1 -0
  32. package/dist/__tests__/templates.test.js +45 -0
  33. package/dist/__tests__/workflowDocumentFixtures.test.d.ts +1 -0
  34. package/dist/__tests__/workflowDocumentFixtures.test.js +78 -0
  35. package/dist/__tests__/workflowExportMatrix.test.d.ts +1 -0
  36. package/dist/__tests__/workflowExportMatrix.test.js +113 -0
  37. package/dist/__tests__/workflowExportSnapshots.test.d.ts +1 -0
  38. package/dist/__tests__/workflowExportSnapshots.test.js +28 -0
  39. package/dist/__tests__/workflowGeneration.test.d.ts +1 -0
  40. package/dist/__tests__/workflowGeneration.test.js +12 -0
  41. package/dist/__tests__/workflowSimulation.test.d.ts +1 -0
  42. package/dist/__tests__/workflowSimulation.test.js +113 -0
  43. package/dist/__tests__/workflowV2Policy.test.d.ts +1 -0
  44. package/dist/__tests__/workflowV2Policy.test.js +80 -0
  45. package/dist/api.d.ts +30 -0
  46. package/dist/api.js +85 -0
  47. package/dist/cli.d.ts +2 -0
  48. package/dist/cli.js +217 -0
  49. package/dist/compat/priorityCompat.d.ts +2 -0
  50. package/dist/compat/priorityCompat.js +24 -0
  51. package/dist/components/features/DocumentGenerateModal.d.ts +9 -0
  52. package/dist/components/features/DocumentGenerateModal.js +114 -0
  53. package/dist/components/features/DocumentIndex.d.ts +19 -0
  54. package/dist/components/features/DocumentIndex.js +51 -0
  55. package/dist/components/features/DocumentViewer.d.ts +9 -0
  56. package/dist/components/features/DocumentViewer.js +253 -0
  57. package/dist/components/features/DocumentWorkspace.d.ts +21 -0
  58. package/dist/components/features/DocumentWorkspace.js +88 -0
  59. package/dist/components/features/TaskSettings.d.ts +209 -0
  60. package/dist/components/features/TaskSettings.js +500 -0
  61. package/dist/components/features/TaskSettings.test.d.ts +1 -0
  62. package/dist/components/features/TaskSettings.test.js +308 -0
  63. package/dist/components/features/settings/CategoryManager.d.ts +19 -0
  64. package/dist/components/features/settings/CategoryManager.js +113 -0
  65. package/dist/components/features/settings/TaxonomyEditor.d.ts +8 -0
  66. package/dist/components/features/settings/TaxonomyEditor.js +98 -0
  67. package/dist/components/features/settings/TaxonomyManager 2.d.ts +52 -0
  68. package/dist/components/features/settings/TaxonomyManager 2.js +75 -0
  69. package/dist/components/features/settings/TaxonomyManager.d.ts +54 -0
  70. package/dist/components/features/settings/TaxonomyManager.js +77 -0
  71. package/dist/components/features/settings/TypeManager.d.ts +10 -0
  72. package/dist/components/features/settings/TypeManager.js +50 -0
  73. package/dist/components/features/settings/WorkflowEditorPrototype.d.ts +15 -0
  74. package/dist/components/features/settings/WorkflowEditorPrototype.js +245 -0
  75. package/dist/components/task/TaskActionHeader.d.ts +20 -0
  76. package/dist/components/task/TaskActionHeader.js +13 -0
  77. package/dist/components/task/TaskCard.d.ts +47 -0
  78. package/dist/components/task/TaskCard.js +326 -0
  79. package/dist/components/task/TaskCard.test.d.ts +1 -0
  80. package/dist/components/task/TaskCard.test.js +95 -0
  81. package/dist/components/task/TaskContextUpload.d.ts +12 -0
  82. package/dist/components/task/TaskContextUpload.js +393 -0
  83. package/dist/components/task/TaskContextUpload.test.d.ts +1 -0
  84. package/dist/components/task/TaskContextUpload.test.js +189 -0
  85. package/dist/components/task/TaskForm.d.ts +105 -0
  86. package/dist/components/task/TaskForm.js +241 -0
  87. package/dist/components/task/TaskForm.test.d.ts +1 -0
  88. package/dist/components/task/TaskForm.test.js +288 -0
  89. package/dist/components/task/TaskKanban 2.d.ts +76 -0
  90. package/dist/components/task/TaskKanban 2.js +1004 -0
  91. package/dist/components/task/TaskKanban.d.ts +76 -0
  92. package/dist/components/task/TaskKanban.empty-column-drop.test.d.ts +1 -0
  93. package/dist/components/task/TaskKanban.empty-column-drop.test.js +66 -0
  94. package/dist/components/task/TaskKanban.js +1026 -0
  95. package/dist/components/task/TaskKanban.test.d.ts +1 -0
  96. package/dist/components/task/TaskKanban.test.js +46 -0
  97. package/dist/components/task/TaskList.d.ts +74 -0
  98. package/dist/components/task/TaskList.js +38 -0
  99. package/dist/components/task/TaskList.test.d.ts +1 -0
  100. package/dist/components/task/TaskList.test.js +270 -0
  101. package/dist/components/task/TaskScreenshotSection.d.ts +15 -0
  102. package/dist/components/task/TaskScreenshotSection.js +22 -0
  103. package/dist/components/ui/LevelSelector.d.ts +13 -0
  104. package/dist/components/ui/LevelSelector.js +25 -0
  105. package/dist/components/ui/LevelSelector.test.d.ts +1 -0
  106. package/dist/components/ui/LevelSelector.test.js +55 -0
  107. package/dist/components/ui/Markdown.d.ts +6 -0
  108. package/dist/components/ui/Markdown.js +94 -0
  109. package/dist/components/ui/Markdown.test.d.ts +1 -0
  110. package/dist/components/ui/Markdown.test.js +38 -0
  111. package/dist/components/ui/Modal.d.ts +16 -0
  112. package/dist/components/ui/Modal.js +49 -0
  113. package/dist/components/ui/MultiSelectFilter.d.ts +10 -0
  114. package/dist/components/ui/MultiSelectFilter.js +71 -0
  115. package/dist/components/ui/MultiSelectFilter.test.d.ts +1 -0
  116. package/dist/components/ui/MultiSelectFilter.test.js +74 -0
  117. package/dist/components/ui/TaxonomyDropdown.d.ts +17 -0
  118. package/dist/components/ui/TaxonomyDropdown.js +145 -0
  119. package/dist/components/ui/TaxonomyDropdown.test.d.ts +1 -0
  120. package/dist/components/ui/TaxonomyDropdown.test.js +130 -0
  121. package/dist/components/views/StandaloneLayout 2.d.ts +8 -0
  122. package/dist/components/views/StandaloneLayout 2.js +1660 -0
  123. package/dist/components/views/StandaloneLayout.d.ts +8 -0
  124. package/dist/components/views/StandaloneLayout.js +2117 -0
  125. package/dist/components/views/WidgetView.d.ts +8 -0
  126. package/dist/components/views/WidgetView.js +221 -0
  127. package/dist/config/envSchema.d.ts +28 -0
  128. package/dist/config/envSchema.js +374 -0
  129. package/dist/config/envSchema.test.d.ts +1 -0
  130. package/dist/config/envSchema.test.js +97 -0
  131. package/dist/config/surfaceBase.d.ts +2 -0
  132. package/dist/config/surfaceBase.js +8 -0
  133. package/dist/core/BulkUpdateFieldsPreview.test.d.ts +1 -0
  134. package/dist/core/BulkUpdateFieldsPreview.test.js +62 -0
  135. package/dist/core/CompletedAt.test.d.ts +1 -0
  136. package/dist/core/CompletedAt.test.js +44 -0
  137. package/dist/core/CreatedBy.test.d.ts +1 -0
  138. package/dist/core/CreatedBy.test.js +60 -0
  139. package/dist/core/EntitlementsPolicy.test.d.ts +1 -0
  140. package/dist/core/EntitlementsPolicy.test.js +145 -0
  141. package/dist/core/InitiativeTemplates.test.d.ts +1 -0
  142. package/dist/core/InitiativeTemplates.test.js +50 -0
  143. package/dist/core/ParentLifecycle.test.d.ts +1 -0
  144. package/dist/core/ParentLifecycle.test.js +98 -0
  145. package/dist/core/ScheduleFields.test.d.ts +1 -0
  146. package/dist/core/ScheduleFields.test.js +197 -0
  147. package/dist/core/SetupState.test.d.ts +1 -0
  148. package/dist/core/SetupState.test.js +113 -0
  149. package/dist/core/SystemAdmin.test.d.ts +1 -0
  150. package/dist/core/SystemAdmin.test.js +295 -0
  151. package/dist/core/TaskTaxonomyValidation.test.d.ts +1 -0
  152. package/dist/core/TaskTaxonomyValidation.test.js +64 -0
  153. package/dist/core/Taskforce.d.ts +1063 -0
  154. package/dist/core/Taskforce.ids.test.d.ts +1 -0
  155. package/dist/core/Taskforce.ids.test.js +168 -0
  156. package/dist/core/Taskforce.js +5981 -0
  157. package/dist/core/Taskforce.realtimeMutation.test.d.ts +1 -0
  158. package/dist/core/Taskforce.realtimeMutation.test.js +76 -0
  159. package/dist/core/WorkspaceDelete.test.d.ts +1 -0
  160. package/dist/core/WorkspaceDelete.test.js +140 -0
  161. package/dist/core/WorkspacePermissions.test.d.ts +1 -0
  162. package/dist/core/WorkspacePermissions.test.js +151 -0
  163. package/dist/core/WorkspacePlanMode.test.d.ts +1 -0
  164. package/dist/core/WorkspacePlanMode.test.js +104 -0
  165. package/dist/hooks/authGuardPolicy.d.ts +26 -0
  166. package/dist/hooks/authGuardPolicy.js +32 -0
  167. package/dist/hooks/authGuardPolicy.test.d.ts +1 -0
  168. package/dist/hooks/authGuardPolicy.test.js +76 -0
  169. package/dist/hooks/useDraggable.d.ts +12 -0
  170. package/dist/hooks/useDraggable.js +65 -0
  171. package/dist/hooks/useRealtimeSync.d.ts +24 -0
  172. package/dist/hooks/useRealtimeSync.js +275 -0
  173. package/dist/hooks/useRealtimeSync.test.d.ts +1 -0
  174. package/dist/hooks/useRealtimeSync.test.js +284 -0
  175. package/dist/hooks/useSyncOrchestrator.d.ts +164 -0
  176. package/dist/hooks/useSyncOrchestrator.js +1427 -0
  177. package/dist/hooks/useSyncOrchestrator.retry-closure.test.d.ts +1 -0
  178. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +367 -0
  179. package/dist/hooks/useTaskforce.d.ts +727 -0
  180. package/dist/hooks/useTaskforce.js +4396 -0
  181. package/dist/hooks/useTaskforce.priority-filters.test.d.ts +1 -0
  182. package/dist/hooks/useTaskforce.priority-filters.test.js +33 -0
  183. package/dist/hooks/useWorkspaceSyncController.d.ts +80 -0
  184. package/dist/hooks/useWorkspaceSyncController.js +598 -0
  185. package/dist/hooks/useWorkspaceSyncController.test.d.ts +1 -0
  186. package/dist/hooks/useWorkspaceSyncController.test.js +236 -0
  187. package/dist/index.d.ts +12 -0
  188. package/dist/index.js +11 -0
  189. package/dist/localization/index.d.ts +8 -0
  190. package/dist/localization/index.js +81 -0
  191. package/dist/localization/locales/en-US.d.ts +151 -0
  192. package/dist/localization/locales/en-US.js +150 -0
  193. package/dist/localization/locales/es-419.d.ts +2 -0
  194. package/dist/localization/locales/es-419.js +150 -0
  195. package/dist/localization/locales/pt-BR.d.ts +2 -0
  196. package/dist/localization/locales/pt-BR.js +150 -0
  197. package/dist/main.d.ts +1 -0
  198. package/dist/main.js +33 -0
  199. package/dist/mcp/optionResolution.d.ts +14 -0
  200. package/dist/mcp/optionResolution.js +126 -0
  201. package/dist/mcp/optionResolution.test.d.ts +1 -0
  202. package/dist/mcp/optionResolution.test.js +39 -0
  203. package/dist/mcp/server.d.ts +1 -0
  204. package/dist/mcp/server.js +1793 -0
  205. package/dist/mcp/structuredCommentValidation.d.ts +6 -0
  206. package/dist/mcp/structuredCommentValidation.js +56 -0
  207. package/dist/mcp/structuredDocValidation.d.ts +6 -0
  208. package/dist/mcp/structuredDocValidation.js +75 -0
  209. package/dist/migrations/billingSchemaParity.test.d.ts +1 -0
  210. package/dist/migrations/billingSchemaParity.test.js +46 -0
  211. package/dist/migrations/clientMigrations.d.ts +9 -0
  212. package/dist/migrations/clientMigrations.js +74 -0
  213. package/dist/migrations/flags.d.ts +6 -0
  214. package/dist/migrations/flags.js +8 -0
  215. package/dist/migrations/taskMigrations.d.ts +71 -0
  216. package/dist/migrations/taskMigrations.js +236 -0
  217. package/dist/migrations/taskMigrations.test.d.ts +1 -0
  218. package/dist/migrations/taskMigrations.test.js +34 -0
  219. package/dist/migrations/taskSchemaMigrations.d.ts +11 -0
  220. package/dist/migrations/taskSchemaMigrations.js +453 -0
  221. package/dist/plugins/index.d.ts +10 -0
  222. package/dist/plugins/index.js +10 -0
  223. package/dist/plugins/vite.d.ts +19 -0
  224. package/dist/plugins/vite.js +271 -0
  225. package/dist/public/android-chrome-192x192.png +0 -0
  226. package/dist/public/android-chrome-512x512.png +0 -0
  227. package/dist/public/apple-touch-icon.png +0 -0
  228. package/dist/public/favicon-16x16.png +0 -0
  229. package/dist/public/favicon-32x32.png +0 -0
  230. package/dist/public/favicon.ico +0 -0
  231. package/dist/public/favicon.png +0 -0
  232. package/dist/public/site.webmanifest +1 -0
  233. package/dist/public/taskforce.png +0 -0
  234. package/dist/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
  235. package/dist/resources/templates/environments/aider.yaml +14 -0
  236. package/dist/resources/templates/environments/antigravity.yaml +10 -0
  237. package/dist/resources/templates/environments/claude.yaml +10 -0
  238. package/dist/resources/templates/environments/cline.yaml +10 -0
  239. package/dist/resources/templates/environments/codex.yaml +13 -0
  240. package/dist/resources/templates/environments/copilot.yaml +10 -0
  241. package/dist/resources/templates/environments/cursor.yaml +9 -0
  242. package/dist/resources/templates/environments/gemini.yaml +9 -0
  243. package/dist/resources/templates/environments/windsurf.yaml +10 -0
  244. package/dist/resources/templates/workflow-sources/README.md +9 -0
  245. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
  246. package/dist/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
  247. package/dist/resources/templates/workflows/collaborate.yaml +104 -0
  248. package/dist/resources/templates/workflows/do.yaml +82 -0
  249. package/dist/resources/templates/workflows/evaluate.yaml +111 -0
  250. package/dist/resources/templates/workflows/execute.yaml +142 -0
  251. package/dist/resources/templates/workflows/plan.yaml +112 -0
  252. package/dist/resources/templates/workflows/review.yaml +109 -0
  253. package/dist/runtime/capabilities.d.ts +8 -0
  254. package/dist/runtime/capabilities.js +16 -0
  255. package/dist/security/virusScan.d.ts +16 -0
  256. package/dist/security/virusScan.js +83 -0
  257. package/dist/server/auth.d.ts +51 -0
  258. package/dist/server/auth.js +266 -0
  259. package/dist/server/auth.test.d.ts +1 -0
  260. package/dist/server/auth.test.js +111 -0
  261. package/dist/server/buildInfo.d.ts +7 -0
  262. package/dist/server/buildInfo.js +100 -0
  263. package/dist/server/buildInfo.test.d.ts +1 -0
  264. package/dist/server/buildInfo.test.js +29 -0
  265. package/dist/server/cors.d.ts +7 -0
  266. package/dist/server/cors.js +76 -0
  267. package/dist/server/cors.test.d.ts +1 -0
  268. package/dist/server/cors.test.js +71 -0
  269. package/dist/server/email.d.ts +28 -0
  270. package/dist/server/email.js +138 -0
  271. package/dist/server/email.test.d.ts +1 -0
  272. package/dist/server/email.test.js +113 -0
  273. package/dist/server/index.cookieProxy.test.d.ts +1 -0
  274. package/dist/server/index.cookieProxy.test.js +19 -0
  275. package/dist/server/index.d.ts +17 -0
  276. package/dist/server/index.js +757 -0
  277. package/dist/server/index.rateLimit.test.d.ts +1 -0
  278. package/dist/server/index.rateLimit.test.js +13 -0
  279. package/dist/server/index.test.d.ts +1 -0
  280. package/dist/server/index.test.js +19 -0
  281. package/dist/server/rateLimit.d.ts +29 -0
  282. package/dist/server/rateLimit.js +99 -0
  283. package/dist/server/rateLimit.test.d.ts +1 -0
  284. package/dist/server/rateLimit.test.js +107 -0
  285. package/dist/server/realtimeSync.auth.test.d.ts +1 -0
  286. package/dist/server/realtimeSync.auth.test.js +62 -0
  287. package/dist/server/realtimeSync.replay.test.d.ts +1 -0
  288. package/dist/server/realtimeSync.replay.test.js +192 -0
  289. package/dist/server/realtimeSync.workspaceIsolation.test.d.ts +1 -0
  290. package/dist/server/realtimeSync.workspaceIsolation.test.js +101 -0
  291. package/dist/server/realtimeSyncWs.d.ts +30 -0
  292. package/dist/server/realtimeSyncWs.js +257 -0
  293. package/dist/server/routes.billing.d.ts +15 -0
  294. package/dist/server/routes.billing.js +991 -0
  295. package/dist/server/routes.billing.test.d.ts +1 -0
  296. package/dist/server/routes.billing.test.js +387 -0
  297. package/dist/server/routes.d.ts +72 -0
  298. package/dist/server/routes.js +4820 -0
  299. package/dist/server/routes.sync.d.ts +17 -0
  300. package/dist/server/routes.sync.integration.test.d.ts +1 -0
  301. package/dist/server/routes.sync.integration.test.js +470 -0
  302. package/dist/server/routes.sync.js +1141 -0
  303. package/dist/server/routes.test.d.ts +1 -0
  304. package/dist/server/routes.test.js +4945 -0
  305. package/dist/server/runtimeMode.d.ts +4 -0
  306. package/dist/server/runtimeMode.js +25 -0
  307. package/dist/server/runtimeMode.test.d.ts +1 -0
  308. package/dist/server/runtimeMode.test.js +26 -0
  309. package/dist/server/securityHeaders.d.ts +3 -0
  310. package/dist/server/securityHeaders.js +25 -0
  311. package/dist/server/securityHeaders.test.d.ts +1 -0
  312. package/dist/server/securityHeaders.test.js +32 -0
  313. package/dist/server/smtpTransport.d.ts +21 -0
  314. package/dist/server/smtpTransport.js +11 -0
  315. package/dist/server/start.d.ts +1 -0
  316. package/dist/server/start.js +17 -0
  317. package/dist/services/formatTransformers.d.ts +29 -0
  318. package/dist/services/formatTransformers.js +56 -0
  319. package/dist/services/templateEngine.d.ts +46 -0
  320. package/dist/services/templateEngine.js +148 -0
  321. package/dist/shared/runtimeContract.d.ts +12 -0
  322. package/dist/shared/runtimeContract.js +23 -0
  323. package/dist/shared/runtimeContract.test.d.ts +1 -0
  324. package/dist/shared/runtimeContract.test.js +23 -0
  325. package/dist/soak/preflight.cli.d.ts +1 -0
  326. package/dist/soak/preflight.cli.js +28 -0
  327. package/dist/soak/preflight.d.ts +26 -0
  328. package/dist/soak/preflight.js +113 -0
  329. package/dist/soak/preflight.test.d.ts +1 -0
  330. package/dist/soak/preflight.test.js +39 -0
  331. package/dist/soak/syncSoakHarness.d.ts +6 -0
  332. package/dist/soak/syncSoakHarness.js +10 -0
  333. package/dist/storage/createDatabaseAdapter.d.ts +2 -0
  334. package/dist/storage/createDatabaseAdapter.js +9 -0
  335. package/dist/storage/databaseAdapter.d.ts +22 -0
  336. package/dist/storage/databaseAdapter.js +1 -0
  337. package/dist/storage/documentIntegrity.d.ts +28 -0
  338. package/dist/storage/documentIntegrity.js +103 -0
  339. package/dist/storage/documentPurge.d.ts +14 -0
  340. package/dist/storage/documentPurge.js +46 -0
  341. package/dist/storage/documentRegistry.d.ts +39 -0
  342. package/dist/storage/documentRegistry.js +115 -0
  343. package/dist/storage/integritySchedule.d.ts +17 -0
  344. package/dist/storage/integritySchedule.js +62 -0
  345. package/dist/storage/objectStorage.d.ts +20 -0
  346. package/dist/storage/objectStorage.js +15 -0
  347. package/dist/storage/objectStorageClient.d.ts +18 -0
  348. package/dist/storage/objectStorageClient.js +301 -0
  349. package/dist/storage/objectStorageConfig.d.ts +2 -0
  350. package/dist/storage/objectStorageConfig.js +45 -0
  351. package/dist/storage/postgresAdapter.d.ts +20 -0
  352. package/dist/storage/postgresAdapter.js +204 -0
  353. package/dist/storage/postgresWorker.d.ts +1 -0
  354. package/dist/storage/postgresWorker.js +110 -0
  355. package/dist/storage/providerConfig.d.ts +6 -0
  356. package/dist/storage/providerConfig.js +11 -0
  357. package/dist/storage/sqliteAdapter.d.ts +14 -0
  358. package/dist/storage/sqliteAdapter.js +28 -0
  359. package/dist/storage/taskAssetStore.d.ts +56 -0
  360. package/dist/storage/taskAssetStore.js +297 -0
  361. package/dist/sync/cloudSyncApi.d.ts +47 -0
  362. package/dist/sync/cloudSyncApi.js +138 -0
  363. package/dist/sync/cloudSyncApi.test.d.ts +1 -0
  364. package/dist/sync/cloudSyncApi.test.js +54 -0
  365. package/dist/sync/encryptionService.d.ts +11 -0
  366. package/dist/sync/encryptionService.js +61 -0
  367. package/dist/sync/encryptionService.test.d.ts +1 -0
  368. package/dist/sync/encryptionService.test.js +52 -0
  369. package/dist/sync/realtimeFeature.d.ts +6 -0
  370. package/dist/sync/realtimeFeature.js +20 -0
  371. package/dist/sync/realtimeFeature.test.d.ts +1 -0
  372. package/dist/sync/realtimeFeature.test.js +30 -0
  373. package/dist/sync/realtimeReconcile.d.ts +30 -0
  374. package/dist/sync/realtimeReconcile.js +90 -0
  375. package/dist/sync/realtimeReconcile.test.d.ts +1 -0
  376. package/dist/sync/realtimeReconcile.test.js +43 -0
  377. package/dist/sync/syncService.d.ts +96 -0
  378. package/dist/sync/syncService.js +423 -0
  379. package/dist/sync/syncService.test.d.ts +1 -0
  380. package/dist/sync/syncService.test.js +484 -0
  381. package/dist/sync/workspaceSyncModel.d.ts +61 -0
  382. package/dist/sync/workspaceSyncModel.js +136 -0
  383. package/dist/sync/workspaceSyncModel.test.d.ts +1 -0
  384. package/dist/sync/workspaceSyncModel.test.js +73 -0
  385. package/dist/test/setup.d.ts +1 -0
  386. package/dist/test/setup.js +15 -0
  387. package/dist/types.d.ts +157 -0
  388. package/dist/types.js +41 -0
  389. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  390. package/dist/ui/assets/index-0W5vyCpn.css +1 -0
  391. package/dist/ui/assets/index-MCZuNNfn.js +23 -0
  392. package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
  393. package/dist/ui/assets/taskforce-BxLPokNB.png +0 -0
  394. package/dist/ui/assets/vendor-dnd-BI1K77C1.js +5 -0
  395. package/dist/ui/assets/vendor-icons-ZFG3SGwo.js +1 -0
  396. package/dist/ui/assets/vendor-markdown-CKYkQHfj.js +29 -0
  397. package/dist/ui/assets/vendor-react-DdIDsh7f.js +9 -0
  398. package/dist/ui/assets/vendor-router-BtiNU7Dl.js +3 -0
  399. package/dist/ui/branding/logos/logo_black_01.png +0 -0
  400. package/dist/ui/branding/logos/logo_black_02.png +0 -0
  401. package/dist/ui/branding/logos/logo_white_01.png +0 -0
  402. package/dist/ui/branding/logos/logo_white_02.png +0 -0
  403. package/dist/ui/favicon/android-chrome-192x192.png +0 -0
  404. package/dist/ui/favicon/android-chrome-512x512.png +0 -0
  405. package/dist/ui/favicon/apple-touch-icon.png +0 -0
  406. package/dist/ui/favicon/favicon-16x16.png +0 -0
  407. package/dist/ui/favicon/favicon-32x32.png +0 -0
  408. package/dist/ui/favicon/favicon.ico +0 -0
  409. package/dist/ui/favicon/favicon.png +0 -0
  410. package/dist/ui/favicon/site.webmanifest +1 -0
  411. package/dist/ui/fonts/RussoOne-Regular.ttf +0 -0
  412. package/dist/ui/images/taskforce.png +0 -0
  413. package/dist/ui/index.html +19 -0
  414. package/dist/utils/checklistMarkdown.d.ts +9 -0
  415. package/dist/utils/checklistMarkdown.js +46 -0
  416. package/dist/utils/constants.d.ts +21 -0
  417. package/dist/utils/constants.icons.test.d.ts +1 -0
  418. package/dist/utils/constants.icons.test.js +40 -0
  419. package/dist/utils/constants.js +100 -0
  420. package/dist/utils/contextFiles.d.ts +8 -0
  421. package/dist/utils/contextFiles.js +54 -0
  422. package/dist/utils/formatting.d.ts +5 -0
  423. package/dist/utils/formatting.js +30 -0
  424. package/dist/utils/planParser.d.ts +22 -0
  425. package/dist/utils/planParser.js +151 -0
  426. package/dist/utils/taskDragZones.d.ts +8 -0
  427. package/dist/utils/taskDragZones.js +14 -0
  428. package/dist/utils/taskDragZones.test.d.ts +1 -0
  429. package/dist/utils/taskDragZones.test.js +14 -0
  430. package/dist/utils/taskHierarchy.d.ts +4 -0
  431. package/dist/utils/taskHierarchy.js +69 -0
  432. package/dist/utils/taskHierarchy.test.d.ts +1 -0
  433. package/dist/utils/taskHierarchy.test.js +38 -0
  434. package/dist/utils/taskParenting.d.ts +3 -0
  435. package/dist/utils/taskParenting.js +24 -0
  436. package/dist/utils/taskParenting.test.d.ts +1 -0
  437. package/dist/utils/taskParenting.test.js +21 -0
  438. package/dist/utils/taskRelations.d.ts +6 -0
  439. package/dist/utils/taskRelations.js +24 -0
  440. package/dist/utils/taskRelations.test.d.ts +1 -0
  441. package/dist/utils/taskRelations.test.js +34 -0
  442. package/dist/utils/taskUtils.d.ts +2 -0
  443. package/dist/utils/taskUtils.js +20 -0
  444. package/dist/utils/taskforceApiClient.d.ts +7 -0
  445. package/dist/utils/taskforceApiClient.js +42 -0
  446. package/dist/utils/workspaceIdentity.d.ts +8 -0
  447. package/dist/utils/workspaceIdentity.js +47 -0
  448. package/dist/utils/workspaceIdentity.test.d.ts +1 -0
  449. package/dist/utils/workspaceIdentity.test.js +32 -0
  450. package/dist/utils/workspaceLifecycle.d.ts +26 -0
  451. package/dist/utils/workspaceLifecycle.js +69 -0
  452. package/dist/utils/workspaceLifecycle.test.d.ts +1 -0
  453. package/dist/utils/workspaceLifecycle.test.js +64 -0
  454. package/package.json +133 -0
  455. package/scripts/check-compat-boundaries.js +48 -0
  456. package/scripts/check-env.ts +24 -0
  457. package/scripts/check-localization-strings.mjs +49 -0
  458. package/scripts/check-runtime-boundaries.mjs +44 -0
  459. package/scripts/debug-global.mjs +34 -0
  460. package/scripts/debug-server.mjs +36 -0
  461. package/scripts/export-sqlite-to-postgres.mjs +125 -0
  462. package/scripts/generate-env-example.ts +8 -0
  463. package/scripts/generate-workflow-templates.mjs +134 -0
  464. package/scripts/mcp-stdio-adapter.mjs +160 -0
  465. package/scripts/postinstall.js +60 -0
  466. package/scripts/release-version-lib.mjs +88 -0
  467. package/scripts/release-version.mjs +72 -0
  468. package/scripts/run-dev-proxy.sh +49 -0
  469. package/scripts/run-e2e-realtime.sh +16 -0
  470. package/scripts/run-smoke.sh +23 -0
  471. package/scripts/run-soak.sh +29 -0
  472. package/scripts/test-global.js +143 -0
  473. package/scripts/update-homebrew-formula.sh +38 -0
  474. package/src/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
  475. package/src/resources/templates/environments/aider.yaml +14 -0
  476. package/src/resources/templates/environments/antigravity.yaml +10 -0
  477. package/src/resources/templates/environments/claude.yaml +10 -0
  478. package/src/resources/templates/environments/cline.yaml +10 -0
  479. package/src/resources/templates/environments/codex.yaml +13 -0
  480. package/src/resources/templates/environments/copilot.yaml +10 -0
  481. package/src/resources/templates/environments/cursor.yaml +9 -0
  482. package/src/resources/templates/environments/gemini.yaml +9 -0
  483. package/src/resources/templates/environments/windsurf.yaml +10 -0
  484. package/src/resources/templates/workflow-sources/README.md +9 -0
  485. package/src/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
  486. package/src/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
  487. package/src/resources/templates/workflows/collaborate.yaml +104 -0
  488. package/src/resources/templates/workflows/do.yaml +82 -0
  489. package/src/resources/templates/workflows/evaluate.yaml +111 -0
  490. package/src/resources/templates/workflows/execute.yaml +142 -0
  491. package/src/resources/templates/workflows/plan.yaml +112 -0
  492. package/src/resources/templates/workflows/review.yaml +109 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,387 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { Readable } from 'stream';
3
+ import Database from 'better-sqlite3';
4
+ import { registerBillingRoutes } from './routes.billing';
5
+ const mockConstructEvent = vi.fn();
6
+ const mockPricesList = vi.fn(async () => ({ data: [], has_more: false }));
7
+ const mockCheckoutCreate = vi.fn(async () => ({ id: 'cs_test', url: 'https://example.test/checkout' }));
8
+ const mockPortalCreate = vi.fn(async () => ({ id: 'bps_test', url: 'https://example.test/portal' }));
9
+ const mockSubscriptionCancel = vi.fn(async () => ({ id: 'sub_test', status: 'canceled' }));
10
+ vi.mock('stripe', () => ({
11
+ default: class StripeMock {
12
+ webhooks = {
13
+ constructEvent: mockConstructEvent
14
+ };
15
+ prices = {
16
+ list: mockPricesList
17
+ };
18
+ checkout = {
19
+ sessions: {
20
+ create: mockCheckoutCreate
21
+ }
22
+ };
23
+ billingPortal = {
24
+ sessions: {
25
+ create: mockPortalCreate
26
+ }
27
+ };
28
+ subscriptions = {
29
+ cancel: mockSubscriptionCancel
30
+ };
31
+ constructor(_apiKey) { }
32
+ }
33
+ }));
34
+ function createMockReq(body, headers = {}) {
35
+ const req = Readable.from([Buffer.from(body, 'utf8')]);
36
+ req.headers = headers;
37
+ return req;
38
+ }
39
+ function createMockRes() {
40
+ const response = {
41
+ statusCode: 200,
42
+ headers: {},
43
+ body: '',
44
+ writeHead: vi.fn((statusCode, headers) => {
45
+ response.statusCode = statusCode;
46
+ response.headers = headers || {};
47
+ return response;
48
+ }),
49
+ end: vi.fn((payload) => {
50
+ response.body = String(payload || '');
51
+ return response;
52
+ })
53
+ };
54
+ return response;
55
+ }
56
+ function setupBillingSchema(db) {
57
+ db.exec(`
58
+ CREATE TABLE user_billing (
59
+ user_id TEXT PRIMARY KEY,
60
+ tenant_id TEXT NOT NULL,
61
+ stripe_customer_id TEXT,
62
+ stripe_subscription_id TEXT,
63
+ stripe_price_id TEXT,
64
+ stripe_status TEXT,
65
+ tier TEXT NOT NULL DEFAULT 'free',
66
+ billing_interval TEXT,
67
+ entitlement_state TEXT NOT NULL DEFAULT 'free',
68
+ trial_end TEXT,
69
+ current_period_end TEXT,
70
+ effective_until TEXT,
71
+ created_at TEXT NOT NULL,
72
+ updated_at TEXT NOT NULL
73
+ );
74
+ CREATE TABLE stripe_webhook_events (
75
+ event_id TEXT PRIMARY KEY,
76
+ tenant_id TEXT NOT NULL,
77
+ event_type TEXT NOT NULL,
78
+ processed_at TEXT NOT NULL
79
+ );
80
+ CREATE TABLE stripe_webhook_failures (
81
+ id TEXT PRIMARY KEY,
82
+ tenant_id TEXT NOT NULL,
83
+ event_id TEXT NOT NULL,
84
+ event_type TEXT,
85
+ reason TEXT NOT NULL,
86
+ payload_excerpt TEXT,
87
+ purge_after TEXT NOT NULL,
88
+ created_at TEXT NOT NULL
89
+ );
90
+ CREATE TABLE billing_price_mappings (
91
+ tenant_id TEXT NOT NULL,
92
+ plan_version_id TEXT NOT NULL,
93
+ billing_interval TEXT NOT NULL,
94
+ stripe_price_id TEXT NOT NULL,
95
+ active INTEGER NOT NULL DEFAULT 1,
96
+ created_at TEXT NOT NULL,
97
+ updated_at TEXT NOT NULL,
98
+ PRIMARY KEY (tenant_id, stripe_price_id)
99
+ );
100
+ CREATE TABLE plan_versions (
101
+ plan_version_id TEXT PRIMARY KEY,
102
+ tenant_id TEXT NOT NULL,
103
+ plan_id TEXT NOT NULL,
104
+ version_number INTEGER NOT NULL,
105
+ is_default INTEGER NOT NULL DEFAULT 0,
106
+ seat_limit INTEGER,
107
+ metadata_json TEXT NOT NULL DEFAULT '{}',
108
+ created_at TEXT NOT NULL,
109
+ updated_at TEXT NOT NULL
110
+ );
111
+ CREATE TABLE account_entitlements (
112
+ account_id TEXT PRIMARY KEY,
113
+ tenant_id TEXT NOT NULL,
114
+ plan_version_id TEXT NOT NULL,
115
+ entitlement_state TEXT NOT NULL DEFAULT 'active',
116
+ effective_at TEXT,
117
+ effective_until TEXT,
118
+ updated_by TEXT,
119
+ created_at TEXT NOT NULL,
120
+ updated_at TEXT NOT NULL
121
+ );
122
+ CREATE TABLE system_settings (
123
+ tenant_id TEXT NOT NULL,
124
+ settings_key TEXT NOT NULL,
125
+ payload TEXT,
126
+ updated_at TEXT NOT NULL,
127
+ PRIMARY KEY (tenant_id, settings_key)
128
+ );
129
+ `);
130
+ }
131
+ function buildBillingRouteHandlers(db, opts) {
132
+ const routes = new Map();
133
+ const tenantId = 'default';
134
+ const core = {
135
+ getDatabaseAdapter: () => db,
136
+ getTenantId: () => tenantId,
137
+ createUserBillingRecord: (userId) => {
138
+ const now = new Date().toISOString();
139
+ db.prepare(`
140
+ INSERT INTO user_billing (
141
+ user_id, tenant_id, tier, entitlement_state, created_at, updated_at
142
+ ) VALUES (?, ?, 'free', 'free', ?, ?)
143
+ ON CONFLICT (user_id) DO NOTHING
144
+ `).run(userId, tenantId, now, now);
145
+ }
146
+ };
147
+ registerBillingRoutes({
148
+ addRoute: (method, path, handler) => routes.set(`${method} ${path}`, handler),
149
+ core,
150
+ context: {
151
+ getRuntimeMode: () => 'cloud'
152
+ },
153
+ ensureAuthenticatedUser: () => true,
154
+ ensureAdminRole: () => opts?.isAdmin !== false,
155
+ requestUserId: () => 'u1',
156
+ resolveErrorStatusCode: (_error, fallback = 500) => fallback,
157
+ auditAdminAction: () => { }
158
+ });
159
+ return routes;
160
+ }
161
+ describe('Billing Webhook Routes', () => {
162
+ const originalEnv = { ...process.env };
163
+ let db;
164
+ let webhookHandler;
165
+ let routeHandlers;
166
+ beforeEach(() => {
167
+ vi.clearAllMocks();
168
+ db = new Database(':memory:');
169
+ setupBillingSchema(db);
170
+ routeHandlers = buildBillingRouteHandlers(db);
171
+ webhookHandler = routeHandlers.get('POST /api/taskforce/billing/webhook');
172
+ process.env.TASKFORCE_BILLING_ENABLED = 'true';
173
+ process.env.TASKFORCE_STRIPE_SECRET_KEY = 'sk_test_123';
174
+ process.env.TASKFORCE_STRIPE_WEBHOOK_SECRET = 'whsec_123';
175
+ });
176
+ afterEach(() => {
177
+ process.env = { ...originalEnv };
178
+ db.close();
179
+ });
180
+ it('returns 400 for invalid webhook signature', async () => {
181
+ mockConstructEvent.mockImplementation(() => {
182
+ throw new Error('invalid signature');
183
+ });
184
+ const req = createMockReq('{"id":"evt_bad"}', {
185
+ 'x-taskforce-runtime-mode': 'cloud',
186
+ 'stripe-signature': 'bad_signature'
187
+ });
188
+ const res = createMockRes();
189
+ await webhookHandler(req, res, {});
190
+ expect(res.statusCode).toBe(400);
191
+ });
192
+ it('returns 200 no-op for duplicate event id', async () => {
193
+ const now = new Date().toISOString();
194
+ db.prepare(`
195
+ INSERT INTO stripe_webhook_events (event_id, tenant_id, event_type, processed_at)
196
+ VALUES (?, 'default', ?, ?)
197
+ `).run('evt_dupe', 'invoice.paid', now);
198
+ mockConstructEvent.mockReturnValue({
199
+ id: 'evt_dupe',
200
+ type: 'invoice.paid',
201
+ data: {
202
+ object: {
203
+ customer: 'cus_1',
204
+ lines: { data: [{ price: { id: 'price_1', recurring: { interval: 'month' } } }] }
205
+ }
206
+ }
207
+ });
208
+ const req = createMockReq('{"id":"evt_dupe"}', {
209
+ 'x-taskforce-runtime-mode': 'cloud',
210
+ 'stripe-signature': 'sig'
211
+ });
212
+ const res = createMockRes();
213
+ await webhookHandler(req, res, {});
214
+ expect(res.statusCode).toBe(200);
215
+ expect(JSON.parse(res.body)).toEqual({ received: true, duplicate: true });
216
+ });
217
+ it('returns 500 on processing failure so Stripe can retry', async () => {
218
+ mockConstructEvent.mockReturnValue({
219
+ id: 'evt_fail',
220
+ type: 'invoice.paid',
221
+ data: {
222
+ object: {
223
+ customer: 'cus_missing',
224
+ lines: { data: [{ price: { id: 'price_1', recurring: { interval: 'month' } } }] }
225
+ }
226
+ }
227
+ });
228
+ const req = createMockReq('{"id":"evt_fail"}', {
229
+ 'x-taskforce-runtime-mode': 'cloud',
230
+ 'stripe-signature': 'sig'
231
+ });
232
+ const res = createMockRes();
233
+ await webhookHandler(req, res, {});
234
+ expect(res.statusCode).toBe(500);
235
+ const failures = db.prepare(`SELECT event_id, reason FROM stripe_webhook_failures WHERE event_id = ?`).all('evt_fail');
236
+ expect(failures.length).toBeGreaterThan(0);
237
+ expect(failures[0]?.reason || '').toContain('Unable to resolve user for invoice event.');
238
+ });
239
+ it('preserves existing entitlement on unknown price_id and logs failure', async () => {
240
+ const now = new Date().toISOString();
241
+ db.prepare(`
242
+ INSERT INTO user_billing (user_id, tenant_id, stripe_customer_id, entitlement_state, created_at, updated_at)
243
+ VALUES ('u1', 'default', 'cus_123', 'free', ?, ?)
244
+ `).run(now, now);
245
+ db.prepare(`
246
+ INSERT INTO account_entitlements (
247
+ account_id, tenant_id, plan_version_id, entitlement_state, effective_at, created_at, updated_at
248
+ ) VALUES ('u1', 'default', 'starter-v1', 'active', ?, ?, ?)
249
+ `).run(now, now, now);
250
+ mockConstructEvent.mockReturnValue({
251
+ id: 'evt_unknown_price',
252
+ type: 'customer.subscription.updated',
253
+ data: {
254
+ object: {
255
+ id: 'sub_123',
256
+ customer: 'cus_123',
257
+ status: 'active',
258
+ trial_end: null,
259
+ metadata: {},
260
+ items: {
261
+ data: [{
262
+ current_period_end: Math.floor(Date.now() / 1000) + 86400,
263
+ price: { id: 'price_unknown', recurring: { interval: 'month' } }
264
+ }]
265
+ }
266
+ }
267
+ }
268
+ });
269
+ const req = createMockReq('{"id":"evt_unknown_price"}', {
270
+ 'x-taskforce-runtime-mode': 'cloud',
271
+ 'stripe-signature': 'sig'
272
+ });
273
+ const res = createMockRes();
274
+ await webhookHandler(req, res, {});
275
+ expect(res.statusCode).toBe(200);
276
+ const entitlement = db.prepare(`
277
+ SELECT plan_version_id
278
+ FROM account_entitlements
279
+ WHERE account_id = 'u1' AND tenant_id = 'default'
280
+ `).get();
281
+ expect(entitlement.plan_version_id).toBe('starter-v1');
282
+ const failure = db.prepare(`
283
+ SELECT reason
284
+ FROM stripe_webhook_failures
285
+ WHERE event_id = 'evt_unknown_price'
286
+ ORDER BY created_at DESC
287
+ LIMIT 1
288
+ `).get();
289
+ expect(failure.reason).toContain('Unknown price mapping');
290
+ });
291
+ it('purges expired webhook failures during webhook processing', async () => {
292
+ const past = new Date(Date.now() - 48 * 60 * 60 * 1000).toISOString();
293
+ const now = new Date().toISOString();
294
+ db.prepare(`
295
+ INSERT INTO stripe_webhook_failures (id, tenant_id, event_id, event_type, reason, payload_excerpt, purge_after, created_at)
296
+ VALUES ('whf_old', 'default', 'evt_old', 'invoice.paid', 'old', '{}', ?, ?)
297
+ `).run(past, now);
298
+ db.prepare(`
299
+ INSERT INTO stripe_webhook_events (event_id, tenant_id, event_type, processed_at)
300
+ VALUES ('evt_dup_for_purge', 'default', 'invoice.paid', ?)
301
+ `).run(now);
302
+ mockConstructEvent.mockReturnValue({
303
+ id: 'evt_dup_for_purge',
304
+ type: 'invoice.paid',
305
+ data: { object: { customer: 'cus_1', lines: { data: [] } } }
306
+ });
307
+ const req = createMockReq('{"id":"evt_dup_for_purge"}', {
308
+ 'x-taskforce-runtime-mode': 'cloud',
309
+ 'stripe-signature': 'sig'
310
+ });
311
+ const res = createMockRes();
312
+ await webhookHandler(req, res, {});
313
+ expect(res.statusCode).toBe(200);
314
+ const row = db.prepare(`SELECT id FROM stripe_webhook_failures WHERE id = 'whf_old'`).get();
315
+ expect(row).toBeUndefined();
316
+ });
317
+ it('creates checkout session with billing success/cancel URLs', async () => {
318
+ const now = new Date().toISOString();
319
+ db.prepare(`
320
+ INSERT INTO plan_versions (plan_version_id, tenant_id, plan_id, version_number, is_default, metadata_json, created_at, updated_at)
321
+ VALUES ('team-v1', 'default', 'team', 1, 1, '{}', ?, ?)
322
+ `).run(now, now);
323
+ db.prepare(`
324
+ INSERT INTO billing_price_mappings (tenant_id, plan_version_id, billing_interval, stripe_price_id, active, created_at, updated_at)
325
+ VALUES ('default', 'team-v1', 'month', 'price_team_month', 1, ?, ?)
326
+ `).run(now, now);
327
+ const checkoutHandler = routeHandlers.get('POST /api/taskforce/billing/checkout-session');
328
+ expect(checkoutHandler).toBeTypeOf('function');
329
+ const req = createMockReq(JSON.stringify({
330
+ tier: 'team',
331
+ interval: 'month'
332
+ }), {
333
+ 'x-taskforce-runtime-mode': 'cloud',
334
+ host: 'app.taskforcehq.ai'
335
+ });
336
+ const res = createMockRes();
337
+ await checkoutHandler(req, res, {});
338
+ expect(res.statusCode).toBe(200);
339
+ expect(mockCheckoutCreate).toHaveBeenCalledTimes(1);
340
+ const firstCall = mockCheckoutCreate.mock.calls[0];
341
+ const args = (Array.isArray(firstCall) ? firstCall[0] : {});
342
+ expect(String(args.success_url || '')).toContain('/billing/success');
343
+ expect(String(args.cancel_url || '')).toContain('/billing/cancel');
344
+ expect(args.line_items?.[0]?.price).toBe('price_team_month');
345
+ });
346
+ it('lists webhook failure diagnostics for system admin', async () => {
347
+ const now = new Date().toISOString();
348
+ const old = new Date(Date.now() - 48 * 60 * 60 * 1000).toISOString();
349
+ db.prepare(`
350
+ INSERT INTO stripe_webhook_failures (id, tenant_id, event_id, event_type, reason, payload_excerpt, purge_after, created_at)
351
+ VALUES ('whf_keep_1', 'default', 'evt_1', 'invoice.paid', 'diagnostic-1', '{"id":"evt_1"}', ?, ?)
352
+ `).run(new Date(Date.now() + 48 * 60 * 60 * 1000).toISOString(), now);
353
+ db.prepare(`
354
+ INSERT INTO stripe_webhook_failures (id, tenant_id, event_id, event_type, reason, payload_excerpt, purge_after, created_at)
355
+ VALUES ('whf_purge_1', 'default', 'evt_old', 'invoice.paid', 'diagnostic-old', '{"id":"evt_old"}', ?, ?)
356
+ `).run(old, now);
357
+ const route = routeHandlers.get('GET /api/taskforce/admin/billing/webhook-failures');
358
+ expect(route).toBeTypeOf('function');
359
+ const req = createMockReq('', {
360
+ 'x-taskforce-runtime-mode': 'cloud'
361
+ });
362
+ req.url = '/api/taskforce/admin/billing/webhook-failures?limit=10';
363
+ const res = createMockRes();
364
+ await route(req, res, {});
365
+ expect(res.statusCode).toBe(200);
366
+ const payload = JSON.parse(res.body);
367
+ expect(payload.purgedExpiredRows).toBeGreaterThanOrEqual(1);
368
+ expect(payload.total).toBeGreaterThanOrEqual(1);
369
+ expect(Array.isArray(payload.rows)).toBe(true);
370
+ expect(payload.rows[0]).toEqual(expect.objectContaining({
371
+ event_id: 'evt_1',
372
+ reason: 'diagnostic-1'
373
+ }));
374
+ });
375
+ it('rejects webhook failure diagnostics for non-admin', async () => {
376
+ const nonAdminHandlers = buildBillingRouteHandlers(db, { isAdmin: false });
377
+ const route = nonAdminHandlers.get('GET /api/taskforce/admin/billing/webhook-failures');
378
+ expect(route).toBeTypeOf('function');
379
+ const req = createMockReq('', {
380
+ 'x-taskforce-runtime-mode': 'cloud'
381
+ });
382
+ req.url = '/api/taskforce/admin/billing/webhook-failures';
383
+ const res = createMockRes();
384
+ await route(req, res, {});
385
+ expect(res.statusCode).toBe(403);
386
+ });
387
+ });
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Taskforce API Routes
3
+ *
4
+ * Extracted from vite.ts plugin to be reusable in both Vite plugin and standalone server.
5
+ * This is a minimal implementation with core routes - additional routes can be added incrementally.
6
+ */
7
+ import { IncomingMessage, ServerResponse } from 'http';
8
+ import { TaskforceCore } from '../core/Taskforce.js';
9
+ import { type TaskforceAuthConfig } from './auth.js';
10
+ import { type ResolvedObjectStorageConfig } from '../storage/objectStorage.js';
11
+ export type RouteHandler = (req: IncomingMessage, res: ServerResponse, params: Record<string, string>) => Promise<void>;
12
+ export interface Route {
13
+ pattern: RegExp;
14
+ keys: string[];
15
+ handler: RouteHandler;
16
+ }
17
+ export declare function parseJsonBody(req: IncomingMessage, maxBytes?: number): Promise<any>;
18
+ /**
19
+ * Create API routes for Taskforce
20
+ *
21
+ * Core routes (29 total):
22
+ *
23
+ * **Task Management (12 routes)**
24
+ * - GET /api/taskforce/config
25
+ * - GET /api/taskforce/tasks
26
+ * - POST /api/taskforce/task
27
+ * - PATCH /api/taskforce/task/:id
28
+ * - DELETE /api/taskforce/task/:id
29
+ * - GET /api/taskforce/archive
30
+ * - POST /api/taskforce/task/:id/complete
31
+ * - POST /api/taskforce/task/:id/cancel
32
+ * - POST /api/taskforce/task/:id/comment
33
+ * - POST /api/taskforce/task/:id/unarchive
34
+ * - POST /api/taskforce/bulk-create
35
+ * - POST /api/taskforce/bulk-archive
36
+ * - POST /api/taskforce/bulk-update-fields
37
+ * - POST /api/taskforce/bulk-update-fields/preview
38
+ *
39
+ * **Configuration Management (10 routes)**
40
+ * - GET /api/taskforce/categories
41
+ * - POST /api/taskforce/categories
42
+ * - GET /api/taskforce/types
43
+ * - POST /api/taskforce/types
44
+ * - GET /api/taskforce/priorities
45
+ * - POST /api/taskforce/priorities
46
+ * - GET /api/taskforce/approaches
47
+ * - POST /api/taskforce/approaches
48
+ * - GET /api/taskforce/taxonomies
49
+ * - POST /api/taskforce/taxonomies
50
+ * - GET /api/taskforce/initiative-templates
51
+ * - POST /api/taskforce/initiative-templates/create
52
+ * - POST /api/taskforce/initiative-templates/clone-checklists
53
+ *
54
+ * **Advanced Features (7 routes)**
55
+ * - POST /api/taskforce/screenshot
56
+ * - GET /api/taskforce/screenshot/:filename
57
+ * - DELETE /api/taskforce/screenshot/:filename
58
+ * - GET /api/taskforce/specialists
59
+ * - GET /api/taskforce/folders
60
+ * - POST /api/taskforce/validate-paths
61
+ * - POST /api/taskforce/export-resources
62
+ * - GET /api/taskforce/health
63
+ */
64
+ export interface RouteContext {
65
+ authConfig?: TaskforceAuthConfig;
66
+ objectStorage?: ResolvedObjectStorageConfig;
67
+ }
68
+ export declare function createRoutes(core: TaskforceCore, context?: RouteContext): Route[];
69
+ export declare function matchRoute(method: string, pathname: string, routes: Route[]): {
70
+ handler: RouteHandler;
71
+ params: Record<string, string>;
72
+ } | null;