@taskforcehq/taskforce 0.3.305 → 0.3.307

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/README.md +0 -2
  2. package/dist/Taskforce.module.css +603 -107
  3. package/dist/TaskforceCore.js +216 -43
  4. package/dist/TaskforceCore.test.js +611 -28
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +46 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
  16. package/dist/components/activity/EntityActivityTimeline.js +81 -0
  17. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  18. package/dist/components/context/ContextAttachmentManager.js +561 -0
  19. package/dist/components/features/AgentsModule.d.ts +14 -1
  20. package/dist/components/features/AgentsModule.js +366 -18
  21. package/dist/components/features/AgentsModule.test.js +507 -8
  22. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
  23. package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
  24. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
  25. package/dist/components/features/DocumentIndex.d.ts +2 -2
  26. package/dist/components/features/DocumentIndex.js +3 -4
  27. package/dist/components/features/DocumentViewer.d.ts +7 -1
  28. package/dist/components/features/DocumentViewer.js +62 -4
  29. package/dist/components/features/DocumentWorkspace.d.ts +10 -2
  30. package/dist/components/features/DocumentWorkspace.js +15 -4
  31. package/dist/components/features/DocumentWorkspace.test.js +51 -1
  32. package/dist/components/features/TaskSettings.d.ts +2 -0
  33. package/dist/components/features/TaskSettings.js +83 -78
  34. package/dist/components/features/TaskSettings.test.js +171 -82
  35. package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
  36. package/dist/components/task/TaskActionHeader.js +11 -5
  37. package/dist/components/task/TaskActionHeader.test.js +10 -0
  38. package/dist/components/task/TaskCard.js +24 -29
  39. package/dist/components/task/TaskCard.test.js +38 -3
  40. package/dist/components/task/TaskContextUpload.js +4 -526
  41. package/dist/components/task/TaskContextUpload.test.js +3 -3
  42. package/dist/components/task/TaskForm.js +61 -116
  43. package/dist/components/task/TaskForm.test.js +110 -8
  44. package/dist/components/task/TaskKanban.d.ts +2 -1
  45. package/dist/components/task/TaskKanban.js +94 -21
  46. package/dist/components/task/TaskKanban.test.js +36 -0
  47. package/dist/components/task/TaskList.js +5 -1
  48. package/dist/components/task/TaskList.test.js +4 -0
  49. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  50. package/dist/components/ui/EditableAvatarButton.js +18 -0
  51. package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
  52. package/dist/components/ui/HierarchyActionBadge.js +5 -0
  53. package/dist/components/views/AppShellHeader.d.ts +3 -1
  54. package/dist/components/views/AppShellHeader.js +27 -11
  55. package/dist/components/views/AppShellHeader.test.js +18 -1
  56. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  57. package/dist/components/views/PlanComparisonPage.js +78 -14
  58. package/dist/components/views/PlanComparisonPage.test.js +257 -0
  59. package/dist/components/views/PlansPage.js +127 -36
  60. package/dist/components/views/PlansPage.test.js +294 -12
  61. package/dist/components/views/StandaloneLayout.js +529 -592
  62. package/dist/components/views/WidgetView.js +10 -8
  63. package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
  64. package/dist/components/views/panels/PlanningDrawer.js +270 -55
  65. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  66. package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
  67. package/dist/components/views/planningScope.d.ts +20 -0
  68. package/dist/components/views/planningScope.js +25 -0
  69. package/dist/components/views/planningScope.test.d.ts +1 -0
  70. package/dist/components/views/planningScope.test.js +60 -0
  71. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
  72. package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
  73. package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
  74. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  75. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  76. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  77. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  78. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  79. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  80. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  81. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  82. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  83. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  84. package/dist/config/envSchema.js +1 -0
  85. package/dist/core/AiProfileService.d.ts +46 -2
  86. package/dist/core/AiProfileService.js +1073 -82
  87. package/dist/core/AiProfileService.test.js +19 -1
  88. package/dist/core/AiProfiles.test.js +1249 -44
  89. package/dist/core/AttachmentLinkService.d.ts +3 -0
  90. package/dist/core/AttachmentLinkService.js +110 -23
  91. package/dist/core/AuthIdentityService.d.ts +107 -0
  92. package/dist/core/AuthIdentityService.js +284 -0
  93. package/dist/core/AuthTokenService.d.ts +4 -0
  94. package/dist/core/AuthTokenService.js +34 -6
  95. package/dist/core/AuthTokenService.test.js +3 -3
  96. package/dist/core/EntitlementsPolicy.test.js +2 -2
  97. package/dist/core/GlobalSettingsService.js +127 -6
  98. package/dist/core/McpTokenService.d.ts +12 -0
  99. package/dist/core/McpTokenService.js +44 -1
  100. package/dist/core/PlanEntitlementService.d.ts +23 -2
  101. package/dist/core/PlanEntitlementService.js +343 -57
  102. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  103. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  104. package/dist/core/PlanVersionPolicy.test.js +35 -2
  105. package/dist/core/PlanningEntities.test.js +418 -4
  106. package/dist/core/SignupMonetizationSettings.test.js +199 -27
  107. package/dist/core/SyncReconciliationService.js +2 -65
  108. package/dist/core/SystemAdmin.test.js +42 -42
  109. package/dist/core/TaskActivityService.d.ts +28 -1
  110. package/dist/core/TaskActivityService.js +227 -46
  111. package/dist/core/TaskActivitySync.test.d.ts +1 -0
  112. package/dist/core/TaskActivitySync.test.js +90 -0
  113. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  114. package/dist/core/TaskAuditTimeline.test.js +96 -0
  115. package/dist/core/Taskforce.d.ts +415 -40
  116. package/dist/core/Taskforce.ids.test.js +58 -0
  117. package/dist/core/Taskforce.js +1543 -266
  118. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  119. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  120. package/dist/core/Taskforce.mcpAuth.test.js +109 -0
  121. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  122. package/dist/core/WorkspaceLifecycleService.js +0 -5
  123. package/dist/core/WorkspacePermissions.test.js +25 -1
  124. package/dist/core/WorkspacePlanMode.test.js +117 -16
  125. package/dist/core/shared.d.ts +1 -1
  126. package/dist/core/shared.js +5 -1
  127. package/dist/core/types.d.ts +75 -2
  128. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
  129. package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
  130. package/dist/hooks/bootstrapTimeouts.js +8 -0
  131. package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
  132. package/dist/hooks/bootstrapTimeouts.test.js +12 -0
  133. package/dist/hooks/sync/bootstrap.js +2 -0
  134. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  135. package/dist/hooks/sync/controlPlane.js +78 -0
  136. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  137. package/dist/hooks/sync/controlPlane.test.js +121 -0
  138. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  139. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  140. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  141. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  142. package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
  143. package/dist/hooks/sync/orchestratorShared.js +129 -48
  144. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  145. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  146. package/dist/hooks/sync/pullLifecycle.js +24 -0
  147. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  148. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  149. package/dist/hooks/sync/recovery.d.ts +16 -2
  150. package/dist/hooks/sync/recovery.js +179 -53
  151. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  152. package/dist/hooks/sync/recovery.test.js +292 -0
  153. package/dist/hooks/sync/transfers.d.ts +16 -3
  154. package/dist/hooks/sync/transfers.js +210 -66
  155. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  156. package/dist/hooks/sync/transfers.test.js +928 -0
  157. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  158. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  159. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  160. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  161. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  162. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  163. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  164. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  165. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  166. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  167. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  168. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  169. package/dist/hooks/useFilterSort.js +13 -13
  170. package/dist/hooks/useFilterSort.test.js +87 -1
  171. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  172. package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
  173. package/dist/hooks/useSyncOrchestrator.js +409 -183
  174. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
  175. package/dist/hooks/useTaskData.js +8 -3
  176. package/dist/hooks/useTaskData.test.js +45 -0
  177. package/dist/hooks/useTaskforce.d.ts +145 -52
  178. package/dist/hooks/useTaskforce.js +592 -253
  179. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  180. package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
  181. package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
  182. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  183. package/dist/hooks/useWorkspaceSyncController.js +13 -2
  184. package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
  185. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  186. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
  187. package/dist/localization/locales/en-US.d.ts +0 -1
  188. package/dist/localization/locales/en-US.js +0 -1
  189. package/dist/localization/locales/es-419.js +0 -1
  190. package/dist/localization/locales/pt-BR.js +0 -1
  191. package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
  192. package/dist/mcp/canonicalAssetHelpers.js +18 -10
  193. package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
  194. package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
  195. package/dist/mcp/clientIntegrations.d.ts +1 -0
  196. package/dist/mcp/clientIntegrations.js +25 -0
  197. package/dist/mcp/clientIntegrations.test.js +14 -3
  198. package/dist/mcp/clientProfileDefaults.js +3 -3
  199. package/dist/mcp/collaborationRegistrar.js +7 -7
  200. package/dist/mcp/documentAssetRegistrar.js +116 -10
  201. package/dist/mcp/runtime.d.ts +3 -0
  202. package/dist/mcp/runtime.js +1099 -185
  203. package/dist/mcp/runtime.test.js +1491 -140
  204. package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
  205. package/dist/mcp/taskPlanningRegistrar.js +48 -0
  206. package/dist/mcp/toolRegistry.d.ts +56 -0
  207. package/dist/mcp/toolRegistry.js +8 -0
  208. package/dist/mcp/toolRegistry.test.js +4 -0
  209. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  210. package/dist/migrations/taskSchemaMigrations.js +192 -61
  211. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  212. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  213. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  214. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  215. package/dist/resources/templates/workflows/plan.yaml +1 -1
  216. package/dist/resources/templates/workflows/review.yaml +2 -2
  217. package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
  218. package/dist/server/aiProfileAvatarAssets.js +319 -0
  219. package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
  220. package/dist/server/aiProfileAvatarAssets.test.js +213 -0
  221. package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
  222. package/dist/server/auth/providers/apple.d.ts +33 -0
  223. package/dist/server/auth/providers/apple.js +82 -0
  224. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  225. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  226. package/dist/server/auth/providers/github.d.ts +26 -0
  227. package/dist/server/auth/providers/github.js +86 -0
  228. package/dist/server/auth/providers/google.d.ts +21 -0
  229. package/dist/server/auth/providers/google.js +56 -0
  230. package/dist/server/auth/providers/types.d.ts +21 -0
  231. package/dist/server/auth/providers/types.js +1 -0
  232. package/dist/server/auth.d.ts +2 -0
  233. package/dist/server/auth.js +6 -3
  234. package/dist/server/documentReviewRoutes.test.js +36 -3
  235. package/dist/server/index.cookieProxy.test.js +1 -0
  236. package/dist/server/index.d.ts +12 -0
  237. package/dist/server/index.js +124 -9
  238. package/dist/server/index.rateLimit.test.js +3 -0
  239. package/dist/server/index.test.js +111 -3
  240. package/dist/server/routes/admin.d.ts +3 -0
  241. package/dist/server/routes/admin.js +459 -28
  242. package/dist/server/routes/annotatedAttachments.js +51 -0
  243. package/dist/server/routes/auth.d.ts +26 -2
  244. package/dist/server/routes/auth.js +1170 -71
  245. package/dist/server/routes/authSupport.d.ts +5 -1
  246. package/dist/server/routes/authSupport.js +13 -2
  247. package/dist/server/routes/billing.js +372 -35
  248. package/dist/server/routes/billing.test.js +595 -12
  249. package/dist/server/routes/documents.d.ts +1 -0
  250. package/dist/server/routes/documents.js +182 -70
  251. package/dist/server/routes/shared.d.ts +28 -2
  252. package/dist/server/routes/shared.js +69 -14
  253. package/dist/server/routes/sync.integration.test.js +658 -39
  254. package/dist/server/routes/sync.js +74 -608
  255. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  256. package/dist/server/routes/syncAuxRoutes.js +91 -0
  257. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  258. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  259. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  260. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  261. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  262. package/dist/server/routes/syncPushRoutes.js +212 -0
  263. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  264. package/dist/server/routes/syncRouteGuards.js +67 -0
  265. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  266. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  267. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  268. package/dist/server/routes/syncRouteTypes.js +1 -0
  269. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  270. package/dist/server/routes/syncSnapshotRoutes.js +182 -0
  271. package/dist/server/routes/tasks.js +55 -10
  272. package/dist/server/routes/workspaces.js +36 -5
  273. package/dist/server/routes.js +147 -11
  274. package/dist/server/routes.test.js +2704 -183
  275. package/dist/services/workflowExportSnapshots.test.js +2 -0
  276. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  277. package/dist/shared/aiProfileSeatScope.js +21 -0
  278. package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
  279. package/dist/shared/aiProfileSurfaceType.js +10 -8
  280. package/dist/shared/passwordPolicy.d.ts +13 -0
  281. package/dist/shared/passwordPolicy.js +84 -0
  282. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  283. package/dist/shared/passwordPolicy.test.js +34 -0
  284. package/dist/storage/objectStorage.d.ts +1 -0
  285. package/dist/storage/objectStorage.js +2 -1
  286. package/dist/storage/objectStorageClient.d.ts +1 -0
  287. package/dist/storage/objectStorageClient.js +41 -8
  288. package/dist/storage/objectStorageClient.test.js +26 -1
  289. package/dist/storage/objectStorageConfig.js +3 -1
  290. package/dist/storage/objectStorageConfig.test.js +13 -1
  291. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  292. package/dist/storage/workspaceAssetStore.js +132 -44
  293. package/dist/storage/workspaceAssetStore.test.js +93 -6
  294. package/dist/styles/fonts.css +70 -0
  295. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  296. package/dist/sync/collaborationSyncPayload.js +19 -11
  297. package/dist/sync/collaborationSyncPayload.test.js +14 -1
  298. package/dist/sync/collaborationSyncState.d.ts +3 -3
  299. package/dist/sync/collaborationSyncState.js +19 -12
  300. package/dist/sync/contentSyncPayload.d.ts +5 -1
  301. package/dist/sync/contentSyncPayload.js +9 -0
  302. package/dist/sync/contentSyncPayload.test.js +39 -0
  303. package/dist/sync/contentSyncState.d.ts +9 -9
  304. package/dist/sync/contentSyncState.js +248 -107
  305. package/dist/sync/planningSyncPayload.js +5 -0
  306. package/dist/sync/planningSyncPayload.test.js +24 -0
  307. package/dist/sync/syncApplyHandlers.d.ts +11 -4
  308. package/dist/sync/syncApplyHandlers.js +115 -42
  309. package/dist/sync/syncApplyHandlers.test.js +251 -4
  310. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  311. package/dist/sync/syncFieldSemantics.js +55 -0
  312. package/dist/sync/syncResourceAdapters.d.ts +46 -0
  313. package/dist/sync/syncResourceAdapters.js +79 -0
  314. package/dist/sync/syncService.d.ts +6 -0
  315. package/dist/sync/syncService.js +65 -1
  316. package/dist/sync/syncService.test.js +96 -3
  317. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  318. package/dist/sync/taskSyncChangeKey.js +143 -0
  319. package/dist/sync/taskSyncPayload.js +3 -8
  320. package/dist/sync/workspacePullFeed.d.ts +4 -0
  321. package/dist/sync/workspacePullFeed.js +132 -72
  322. package/dist/sync/workspacePullFeed.test.js +92 -0
  323. package/dist/sync/workspaceRepair.js +5 -2
  324. package/dist/sync/workspaceSyncModel.d.ts +73 -6
  325. package/dist/sync/workspaceSyncModel.js +342 -73
  326. package/dist/sync/workspaceSyncModel.test.js +559 -14
  327. package/dist/sync/workspaceSyncState.d.ts +17 -0
  328. package/dist/sync/workspaceSyncState.js +2 -1
  329. package/dist/sync/workspaceSyncSurface.js +3 -8
  330. package/dist/types.d.ts +50 -2
  331. package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
  332. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
  333. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
  334. package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
  335. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  336. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  337. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  338. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  339. package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
  340. package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
  341. package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
  342. package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
  343. package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
  344. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  345. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  346. package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
  347. package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
  348. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  349. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  350. package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
  351. package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
  352. package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
  353. package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
  354. package/dist/ui/assets/index-607WPo_X.js +4 -0
  355. package/dist/ui/assets/index-CYyodXsg.css +1 -0
  356. package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
  357. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  358. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  359. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  360. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  361. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  362. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  363. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  364. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  365. package/dist/ui/fonts/Noir_medium.otf +0 -0
  366. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  367. package/dist/ui/fonts/Noir_regular.otf +0 -0
  368. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  369. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  370. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  371. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  372. package/dist/ui/index.html +3 -3
  373. package/dist/ui/product/agent manager.png +0 -0
  374. package/dist/ui/product/agent_manager_02.png +0 -0
  375. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  376. package/dist/utils/aiProfileEvents.d.ts +7 -0
  377. package/dist/utils/aiProfileEvents.js +6 -0
  378. package/dist/utils/assignees.d.ts +8 -0
  379. package/dist/utils/assignees.js +10 -1
  380. package/dist/utils/assignees.test.d.ts +1 -0
  381. package/dist/utils/assignees.test.js +25 -0
  382. package/dist/utils/avatarDisplay.d.ts +1 -0
  383. package/dist/utils/avatarDisplay.js +15 -0
  384. package/dist/utils/avatarUpload.d.ts +27 -0
  385. package/dist/utils/avatarUpload.js +132 -0
  386. package/dist/utils/avatarUpload.test.d.ts +1 -0
  387. package/dist/utils/avatarUpload.test.js +40 -0
  388. package/dist/utils/bootstrapTrace.d.ts +7 -0
  389. package/dist/utils/bootstrapTrace.js +29 -0
  390. package/dist/utils/commercialLifecyclePresentation.js +3 -0
  391. package/dist/utils/contextAssetEvents.d.ts +2 -0
  392. package/dist/utils/contextFiles.d.ts +3 -1
  393. package/dist/utils/contextFiles.js +2 -1
  394. package/dist/utils/syncEventDetails.d.ts +3 -0
  395. package/dist/utils/syncEventDetails.js +64 -0
  396. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  397. package/dist/utils/syncEventDetails.test.js +23 -0
  398. package/dist/utils/syncEventPresentation.d.ts +15 -0
  399. package/dist/utils/syncEventPresentation.js +129 -0
  400. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  401. package/dist/utils/syncEventPresentation.test.js +64 -0
  402. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  403. package/dist/utils/syncStatusPresentation.js +217 -0
  404. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  405. package/dist/utils/syncStatusPresentation.test.js +164 -0
  406. package/dist/utils/taskActivity.d.ts +9 -1
  407. package/dist/utils/taskActivity.js +290 -22
  408. package/dist/utils/taskActivity.test.js +141 -8
  409. package/dist/utils/taskSearch.d.ts +22 -0
  410. package/dist/utils/taskSearch.js +87 -0
  411. package/dist/utils/taskSearch.test.d.ts +1 -0
  412. package/dist/utils/taskSearch.test.js +69 -0
  413. package/dist/utils/taskUtils.js +10 -3
  414. package/dist/utils/taskUtils.test.d.ts +1 -0
  415. package/dist/utils/taskUtils.test.js +19 -0
  416. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  417. package/dist/utils/workspaceSyncPresentation.js +68 -2
  418. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  419. package/package.json +3 -2
  420. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  421. package/scripts/run-e2e-realtime.sh +17 -3
  422. package/scripts/run-smoke.sh +17 -5
  423. package/scripts/run-soak.sh +17 -5
  424. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  425. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  426. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  427. package/src/resources/templates/workflows/plan.yaml +1 -1
  428. package/src/resources/templates/workflows/review.yaml +2 -2
  429. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
  430. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
  431. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
  432. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
  433. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
  434. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  435. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
  436. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  437. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
  438. package/dist/ui/assets/index-C2-OXZV7.css +0 -1
  439. package/dist/ui/assets/index-DcSI5F86.js +0 -6
  440. package/scripts/migrate-planning-model.ts +0 -233
@@ -15,6 +15,7 @@ import logoDark from './assets/branding/logos/logo_dark.svg';
15
15
  import taskforceBg from './assets/images/taskforce.png';
16
16
  import { isLightThemeFamily } from './utils/theme';
17
17
  import { Cloud, LaptopMinimal } from 'lucide-react';
18
+ import { getPasswordPolicyGuidance, validatePasswordPolicy } from './shared/passwordPolicy';
18
19
  function isDebugModeEnabled() {
19
20
  const runtimeOverride = globalThis.__DEBUG_MODE__;
20
21
  if (typeof runtimeOverride === 'boolean')
@@ -58,18 +59,21 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
58
59
  const [loginEmail, setLoginEmail] = useState('');
59
60
  const [loginDisplayName, setLoginDisplayName] = useState('');
60
61
  const [loginPassword, setLoginPassword] = useState('');
62
+ const [loginPasswordConfirm, setLoginPasswordConfirm] = useState('');
61
63
  const [authMode, setAuthMode] = useState('login');
62
64
  const [verificationToken, setVerificationToken] = useState('');
63
65
  const [pendingVerificationWorkspaceSetupRequired, setPendingVerificationWorkspaceSetupRequired] = useState(false);
64
66
  const [pendingVerificationCommercialState, setPendingVerificationCommercialState] = useState(null);
65
67
  const [pendingVerificationRedirectPath, setPendingVerificationRedirectPath] = useState(null);
66
68
  const [pendingPostAuthRedirect, setPendingPostAuthRedirect] = useState(null);
69
+ const [commercialOnboardingRedirectActive, setCommercialOnboardingRedirectActive] = useState(false);
67
70
  const [resetToken, setResetToken] = useState('');
68
71
  const [inviteToken, setInviteToken] = useState('');
69
72
  const [inviteEmail, setInviteEmail] = useState(null);
70
73
  const [inviteWorkspaceId, setInviteWorkspaceId] = useState(null);
71
74
  const [inviteResolution, setInviteResolution] = useState('unknown');
72
75
  const [invitePasswordRequired, setInvitePasswordRequired] = useState(false);
76
+ const [inviteOAuthProviders, setInviteOAuthProviders] = useState([]);
73
77
  const [loginNotice, setLoginNotice] = useState(null);
74
78
  const [loginError, setLoginError] = useState(null);
75
79
  const [loginErrorCode, setLoginErrorCode] = useState(null);
@@ -109,7 +113,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
109
113
  onTaskCountChange,
110
114
  onClose
111
115
  });
112
- const { runtimeMode, workspaceSwitchingEnabled, currentWorkspaceId, configLoaded, cloudAuthConfigured, authRequiredForApi, authBlocked, isAuthenticated, hasBetaAccess, authSessionResolved, workspaceBootstrapPending, bootstrapPhase, bootstrapError, setupState, runtimeCapabilities, refreshSetupContext, retryBootstrapChecks, createWorkspace, saveWorkspaceProfile, fetchWorkspaces, applyWorkspaceSyncStateSnapshot, workspaceCloudSyncEnabled, workspaceSyncPhase, workspaceSyncSetupIntent, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncBusy, workspaceLastErrorMessage, retryWorkspaceCloudSync, settingsModel, fetchTasks, loginWithCredentials, registerWithCredentials, requestEmailVerification, confirmEmailVerification, requestPasswordReset, confirmPasswordReset, inspectInviteAcceptance, acceptInviteWithToken, joinInviteWithToken, authUserEmail, currentTheme, logout } = taskforceState;
116
+ const { runtimeMode, workspaceSwitchingEnabled, currentWorkspaceId, cloudAuthConfigured, authRequiredForApi, authBlocked, isAuthenticated, hasBetaAccess, authSessionResolved, setupState, runtimeCapabilities, refreshSetupContext, retryBootstrapChecks, createWorkspace, saveWorkspaceProfile, fetchWorkspaces, applyWorkspaceSyncStateSnapshot, workspaceCloudSyncEnabled, workspaceSyncPhase, workspaceSyncSetupIntent, workspaceSyncSummary, workspaceSyncRecommendedAction, workspaceSyncBusy, workspaceLastErrorMessage, retryWorkspaceCloudSync, settingsModel, fetchTasks, bootstrapState, loginWithCredentials, beginOAuthLogin, availableAuthProviders, registerWithCredentials, requestEmailVerification, confirmEmailVerification, requestPasswordReset, confirmPasswordReset, inspectInviteAcceptance, acceptInviteWithToken, joinInviteWithToken, authUserEmail, currentTheme, logout } = taskforceState;
113
117
  const persistWorkspaceSyncStatePatch = useCallback(async (workspaceId, patch) => {
114
118
  const response = await fetch('/api/taskforce/ui-state', {
115
119
  method: 'POST',
@@ -216,6 +220,9 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
216
220
  && !isPricingRoute
217
221
  && !isPlansRoute
218
222
  && !isPlansScreen;
223
+ const cloudAccountAccessPending = runtimeMode === 'cloud'
224
+ && isAuthenticated
225
+ && (!authSessionResolved || !accountAccessGateResolved);
219
226
  const directRegistrationEnabled = cloudAuthConfigured;
220
227
  const authPageTitle = useMemo(() => {
221
228
  switch (authMode) {
@@ -238,7 +245,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
238
245
  const setupIntent = useMemo(() => String(new URLSearchParams(location.search).get('intent') || '').trim().toLowerCase(), [location.search]);
239
246
  const isCreateWorkspaceIntent = isSetupRoute && setupStep === 'workspace' && setupIntent === 'create-workspace';
240
247
  const shouldHoldForAuthBootstrap = mode !== 'widget'
241
- && !authSessionResolved
248
+ && bootstrapState.authPending
242
249
  && !isLoginRoute
243
250
  && !isSetupRoute
244
251
  && !isPricingRoute
@@ -266,23 +273,48 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
266
273
  const needsWorkspaceSetup = workspaceLifecycle.needsWorkspaceSetup;
267
274
  const hasSetupReadError = workspaceLifecycle.hasSetupReadError;
268
275
  const shouldHoldForSetupBootstrap = mode !== 'widget'
269
- && authSessionResolved
276
+ && bootstrapState.auth.resolved
270
277
  && !shouldForceLogin
271
278
  && !shouldForceComingSoon
272
279
  && !isPricingRoute
273
280
  && !isPlansRoute
274
281
  && !isPlansScreen
275
- && (!configLoaded || workspaceBootstrapPending || bootstrapPhase === 'stalled')
282
+ && !isLoginRoute
283
+ && bootstrapState.appPending
276
284
  && (isSetupRoute || runtimeMode === 'cloud' || isLikelyCloudAppHost);
277
- const bootstrapSubtitle = useMemo(() => {
278
- if (bootstrapPhase === 'auth')
279
- return 'Verifying session...';
280
- if (bootstrapPhase === 'workspace')
281
- return 'Resolving workspace access...';
282
- if (bootstrapPhase === 'config')
283
- return 'Loading configuration...';
284
- return 'Checking account, workspace access, and setup status...';
285
- }, [bootstrapPhase]);
285
+ const shouldHoldForCommercialOnboardingRedirect = runtimeMode === 'cloud'
286
+ && commercialOnboardingRedirectActive
287
+ && !isPlansScreen;
288
+ const bootstrapSubtitle = bootstrapState.subtitle;
289
+ const showGuidedWorkspaceSetup = isCreateWorkspaceIntent
290
+ || (isSetupRoute && Boolean(activeCloudWorkspaceImport))
291
+ || (isSetupRoute && setupGateActive && (hasSetupReadError || needsGlobalSetup || needsWorkspaceSetup));
292
+ const shellRenderState = useMemo(() => {
293
+ if (shouldHoldForAuthBootstrap)
294
+ return 'auth-bootstrap';
295
+ if (shouldHoldForCommercialOnboardingRedirect)
296
+ return 'app-bootstrap';
297
+ if (shouldHoldForSetupBootstrap)
298
+ return 'app-bootstrap';
299
+ if (isLoginRoute)
300
+ return 'login';
301
+ if (shouldForceLogin && !isLoginRoute)
302
+ return 'login-redirect';
303
+ if (isComingSoonRoute && shouldForceComingSoon)
304
+ return 'coming-soon';
305
+ if (showGuidedWorkspaceSetup)
306
+ return 'guided-setup';
307
+ return 'app';
308
+ }, [
309
+ isComingSoonRoute,
310
+ isLoginRoute,
311
+ shouldForceComingSoon,
312
+ shouldForceLogin,
313
+ shouldHoldForCommercialOnboardingRedirect,
314
+ shouldHoldForAuthBootstrap,
315
+ shouldHoldForSetupBootstrap,
316
+ showGuidedWorkspaceSetup
317
+ ]);
286
318
  const isPlaceholderWorkspaceName = useCallback((name, workspaceId, _description) => {
287
319
  const normalizedName = String(name || '').trim().toLowerCase();
288
320
  const normalizedWorkspaceId = String(workspaceId || '').trim().toLowerCase();
@@ -299,7 +331,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
299
331
  setSetupModeChoice(modeValue);
300
332
  }, [setupState?.mode]);
301
333
  useEffect(() => {
302
- if (runtimeMode !== 'cloud' || !isAuthenticated || !authSessionResolved) {
334
+ if (runtimeMode !== 'cloud' || !isAuthenticated) {
335
+ setAccountAccessGate(null);
336
+ setAccountAccessGateResolved(false);
337
+ return;
338
+ }
339
+ if (!authSessionResolved) {
303
340
  setAccountAccessGate(null);
304
341
  setAccountAccessGateResolved(false);
305
342
  return;
@@ -637,27 +674,95 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
637
674
  setPendingVerificationRedirectPath(null);
638
675
  }, [authMode, isLoginRoute, loginRouteMode]);
639
676
  useEffect(() => {
640
- if (!isLoginRoute || !pendingPostAuthRedirect || !authSessionResolved || !isAuthenticated)
677
+ if (authMode === 'register')
641
678
  return;
642
- if (runtimeMode === 'cloud' && !pendingPostAuthRedirect.commercialOnboardingGate && !accountAccessGateResolved) {
679
+ setLoginPasswordConfirm('');
680
+ }, [authMode]);
681
+ useEffect(() => {
682
+ if (!pendingPostAuthRedirect || !isAuthenticated)
683
+ return;
684
+ if (!pendingPostAuthRedirect.commercialOnboardingGate && (!authSessionResolved || cloudAccountAccessPending)) {
643
685
  return;
644
686
  }
645
- if (!pendingPostAuthRedirect.commercialOnboardingGate && pendingPostAuthRedirect.workspaceSetupRequired) {
646
- navigate(resolveWorkspaceSetupPath(), { replace: true });
687
+ const destination = !pendingPostAuthRedirect.commercialOnboardingGate && pendingPostAuthRedirect.workspaceSetupRequired
688
+ ? resolveWorkspaceSetupPath()
689
+ : pendingPostAuthRedirect.path;
690
+ const currentRoute = `${location.pathname}${location.search}${location.hash || ''}`;
691
+ if (currentRoute !== destination) {
692
+ navigate(destination, { replace: true });
647
693
  }
648
- else {
649
- navigate(pendingPostAuthRedirect.path, { replace: true });
694
+ }, [
695
+ authSessionResolved,
696
+ cloudAccountAccessPending,
697
+ isAuthenticated,
698
+ location.hash,
699
+ location.pathname,
700
+ location.search,
701
+ navigate,
702
+ pendingPostAuthRedirect,
703
+ resolveWorkspaceSetupPath
704
+ ]);
705
+ useEffect(() => {
706
+ if (!commercialOnboardingRedirectActive)
707
+ return;
708
+ if (!authSessionResolved) {
709
+ return;
650
710
  }
711
+ if (!isAuthenticated) {
712
+ setCommercialOnboardingRedirectActive(false);
713
+ setPendingPostAuthRedirect(null);
714
+ return;
715
+ }
716
+ if (accountAccessGateResolved && accountAccessGate?.canAccessApp === true) {
717
+ setLoginEmail('');
718
+ setLoginDisplayName('');
719
+ setLoginPassword('');
720
+ setLoginPasswordConfirm('');
721
+ setPendingPostAuthRedirect(null);
722
+ setCommercialOnboardingRedirectActive(false);
723
+ return;
724
+ }
725
+ const destination = pendingPostAuthRedirect?.commercialOnboardingGate
726
+ ? pendingPostAuthRedirect.path
727
+ : planSelectionPath;
728
+ const currentRoute = `${location.pathname}${location.search}${location.hash || ''}`;
729
+ if (currentRoute !== destination) {
730
+ navigate(destination, { replace: true });
731
+ }
732
+ }, [
733
+ accountAccessGate?.canAccessApp,
734
+ accountAccessGateResolved,
735
+ authSessionResolved,
736
+ commercialOnboardingRedirectActive,
737
+ isAuthenticated,
738
+ location.hash,
739
+ location.pathname,
740
+ location.search,
741
+ navigate,
742
+ pendingPostAuthRedirect,
743
+ planSelectionPath
744
+ ]);
745
+ useEffect(() => {
746
+ if (!pendingPostAuthRedirect || !isAuthenticated)
747
+ return;
748
+ const destination = !pendingPostAuthRedirect.commercialOnboardingGate && pendingPostAuthRedirect.workspaceSetupRequired
749
+ ? resolveWorkspaceSetupPath()
750
+ : pendingPostAuthRedirect.path;
751
+ const currentRoute = `${location.pathname}${location.search}${location.hash || ''}`;
752
+ if (currentRoute !== destination)
753
+ return;
754
+ if (pendingPostAuthRedirect.commercialOnboardingGate)
755
+ return;
651
756
  setLoginEmail('');
652
757
  setLoginDisplayName('');
653
758
  setLoginPassword('');
759
+ setLoginPasswordConfirm('');
654
760
  setPendingPostAuthRedirect(null);
655
761
  }, [
656
- accountAccessGateResolved,
657
- authSessionResolved,
762
+ location.hash,
763
+ location.pathname,
764
+ location.search,
658
765
  isAuthenticated,
659
- isLoginRoute,
660
- navigate,
661
766
  pendingPostAuthRedirect,
662
767
  resolveWorkspaceSetupPath,
663
768
  runtimeMode
@@ -679,6 +784,9 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
679
784
  setInviteEmail(inspected.email || null);
680
785
  setInviteWorkspaceId(inspected.workspaceId || null);
681
786
  setInvitePasswordRequired(inspected.passwordRequired === true);
787
+ // Capture OAuth providers available for invite-claim (pending_setup only)
788
+ const oauthMethods = (inspected.availableMethods || []).filter(m => m === 'google' || m === 'github' || m === 'apple');
789
+ setInviteOAuthProviders(inspected.inviteeState === 'pending_setup' ? oauthMethods : []);
682
790
  const inviteMatchesAuthenticatedUser = Boolean(isAuthenticated
683
791
  && authUserEmail
684
792
  && inspected.email
@@ -704,6 +812,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
704
812
  setInviteWorkspaceId(null);
705
813
  setInviteResolution('invalid');
706
814
  setInvitePasswordRequired(false);
815
+ setInviteOAuthProviders([]);
707
816
  setLoginError(formatAuthError(inspected));
708
817
  setLoginErrorCode(inspected.code || inspected.state || null);
709
818
  }
@@ -730,6 +839,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
730
839
  const resetCooldownSeconds = Math.max(0, Math.ceil((resetCooldownUntil - cooldownNow) / 1000));
731
840
  const verifyCooldownActive = verifyCooldownSeconds > 0;
732
841
  const resetCooldownActive = resetCooldownSeconds > 0;
842
+ const registerPasswordGuidance = useMemo(() => getPasswordPolicyGuidance(), []);
733
843
  const formatAuthError = (result) => {
734
844
  const message = result.error || 'Request failed.';
735
845
  const code = result.code || result.state;
@@ -756,7 +866,15 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
756
866
  useEffect(() => {
757
867
  if (mode === 'widget')
758
868
  return;
759
- if (workspaceBootstrapPending)
869
+ if (isLoginRoute && loginBusy) {
870
+ return;
871
+ }
872
+ const shouldBypassWorkspacePendingForAccessGate = runtimeMode === 'cloud'
873
+ && isAuthenticated
874
+ && accountAccessGateResolved
875
+ && accountAccessGate?.canAccessApp === false
876
+ && accountAccessGate?.canAccessPlans !== false;
877
+ if (bootstrapState.workspace.pending && !shouldBypassWorkspacePendingForAccessGate)
760
878
  return;
761
879
  if (shouldForceComingSoon) {
762
880
  if (!isComingSoonRoute)
@@ -775,10 +893,11 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
775
893
  && isAuthenticated
776
894
  && !shouldStayOnInviteRoute
777
895
  && (Boolean(pendingPostAuthRedirect)
778
- || workspaceBootstrapPending
896
+ || bootstrapState.workspace.pending
779
897
  || authMode === 'register'
780
898
  || authMode === 'verify'
781
- || (runtimeMode === 'cloud' && (!configLoaded || !accountAccessGateResolved)));
899
+ || !bootstrapState.config.loaded
900
+ || cloudAccountAccessPending);
782
901
  if (shouldDelayAuthenticatedLoginRedirect) {
783
902
  return;
784
903
  }
@@ -796,6 +915,23 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
796
915
  if (isLoginRoute && !isAuthenticated) {
797
916
  return;
798
917
  }
918
+ if (pendingPostAuthRedirect && isAuthenticated) {
919
+ return;
920
+ }
921
+ const shouldHoldAuthenticatedAuthRoute = isLoginRoute
922
+ && isAuthenticated
923
+ && (authMode === 'register'
924
+ || authMode === 'verify'
925
+ || (authMode === 'invite' && inviteToken.trim().length > 0));
926
+ if (shouldHoldAuthenticatedAuthRoute) {
927
+ return;
928
+ }
929
+ if (commercialOnboardingRedirectActive) {
930
+ return;
931
+ }
932
+ if (isPlansScreen) {
933
+ return;
934
+ }
799
935
  if (shouldForceAccountAccessGate) {
800
936
  if (!isPlansScreen) {
801
937
  const gate = encodeURIComponent(String(accountAccessGate?.gate || 'plan_selection_required'));
@@ -812,6 +948,16 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
812
948
  }
813
949
  return;
814
950
  }
951
+ if (isPlansScreen && cloudAccountAccessPending) {
952
+ return;
953
+ }
954
+ if (isPlansScreen
955
+ && runtimeMode === 'cloud'
956
+ && accountAccessGateResolved
957
+ && accountAccessGate?.canAccessApp === false
958
+ && accountAccessGate?.canAccessPlans !== false) {
959
+ return;
960
+ }
815
961
  if (setupGateActive) {
816
962
  if (hasSetupReadError) {
817
963
  if (!isSetupRoute || setupStep !== 'error') {
@@ -849,9 +995,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
849
995
  isComingSoonRoute,
850
996
  isPlansRoute,
851
997
  isPlansScreen,
998
+ accountAccessGate,
852
999
  accountAccessGate?.gate,
853
1000
  accountAccessGateResolved,
854
1001
  authMode,
1002
+ commercialOnboardingRedirectActive,
1003
+ cloudAccountAccessPending,
855
1004
  setupGateActive,
856
1005
  setupState,
857
1006
  hasSetupReadError,
@@ -860,9 +1009,11 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
860
1009
  needsGlobalSetup,
861
1010
  needsWorkspaceSetup,
862
1011
  setupStep,
863
- workspaceBootstrapPending,
864
- configLoaded,
1012
+ bootstrapState,
865
1013
  runtimeMode,
1014
+ loginBusy,
1015
+ isAuthenticated,
1016
+ accountAccessGateResolved,
866
1017
  inviteToken,
867
1018
  location.pathname,
868
1019
  location.search,
@@ -877,7 +1028,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
877
1028
  return;
878
1029
  if (runtimeMode !== 'local')
879
1030
  return;
880
- if (!configLoaded)
1031
+ if (!bootstrapState.config.loaded)
881
1032
  return;
882
1033
  if (isLoginRoute || isSetupRoute)
883
1034
  return;
@@ -885,7 +1036,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
885
1036
  if (!workspaceId || workspaceId === 'default') {
886
1037
  navigate('/setup?step=workspace', { replace: true });
887
1038
  }
888
- }, [mode, runtimeMode, configLoaded, isLoginRoute, isSetupRoute, currentWorkspaceId, navigate]);
1039
+ }, [mode, runtimeMode, bootstrapState.config.loaded, isLoginRoute, isSetupRoute, currentWorkspaceId, navigate]);
889
1040
  const handleRetryBootstrap = useCallback(async () => {
890
1041
  setBootstrapRetryBusy(true);
891
1042
  try {
@@ -913,13 +1064,13 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
913
1064
  params.set('screen', 'plans');
914
1065
  return _jsx(Navigate, { to: `/?${params.toString()}${location.hash || ''}`, replace: true });
915
1066
  }
916
- if (shouldHoldForAuthBootstrap) {
1067
+ if (shellRenderState === 'auth-bootstrap') {
917
1068
  return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, children: _jsxs("div", { className: authStyles.loginCard, children: [_jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsx("h1", { className: authStyles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: authStyles.loginSubtitle, children: "Checking your session..." })] }) }) }));
918
1069
  }
919
- if (shouldHoldForSetupBootstrap) {
920
- return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, children: _jsxs("div", { className: authStyles.loginCard, children: [_jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsx("h1", { className: authStyles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: authStyles.loginSubtitle, children: bootstrapSubtitle }), bootstrapPhase === 'stalled' && (_jsxs(_Fragment, { children: [_jsx("p", { className: authStyles.loginError, children: bootstrapError || 'Startup checks timed out.' }), _jsx("button", { className: styles.submitBtn, disabled: bootstrapRetryBusy, onClick: handleRetryBootstrap, children: bootstrapRetryBusy ? 'Retrying...' : 'Retry checks' }), isCloudRuntime && (_jsx("button", { className: styles.cancelBtn, disabled: bootstrapRetryBusy, onClick: handleGoToSignIn, children: "Go to sign-in" }))] }))] }) }) }));
1070
+ if (shellRenderState === 'app-bootstrap') {
1071
+ return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, children: _jsxs("div", { className: authStyles.loginCard, children: [_jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsx("h1", { className: authStyles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: authStyles.loginSubtitle, children: bootstrapSubtitle }), bootstrapState.stalled && (_jsxs(_Fragment, { children: [_jsx("p", { className: authStyles.loginError, children: bootstrapState.error || 'Startup checks timed out.' }), _jsx("button", { className: styles.submitBtn, disabled: bootstrapRetryBusy, onClick: handleRetryBootstrap, children: bootstrapRetryBusy ? 'Retrying...' : 'Retry checks' }), isCloudRuntime && (_jsx("button", { className: styles.cancelBtn, disabled: bootstrapRetryBusy, onClick: handleGoToSignIn, children: "Go to sign-in" }))] }))] }) }) }));
921
1072
  }
922
- if (isLoginRoute) {
1073
+ if (shellRenderState === 'login') {
923
1074
  return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, style: {
924
1075
  backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
925
1076
  }, children: _jsxs("div", { className: authStyles.loginCard, children: [!isCloudRuntime && !shouldForceLogin && (_jsx("button", { className: authStyles.loginCloseBtn, "aria-label": "Close sign in", "data-testid": "auth-close-button", onClick: () => navigate(nextPath, { replace: true }), children: "\u00D7" })), _jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsxs("h1", { className: authStyles.loginTitle, children: ["TASKFORCE ", _jsx("span", { className: authStyles.loginTitleAccent, children: "HQ" })] })] }), _jsxs("p", { className: authStyles.loginSubtitle, children: [authMode === 'login' && 'Sign in with your account credentials.', authMode === 'register' && 'Create your Taskforce account.', authMode === 'verify' && 'Enter your verification token.', authMode === 'forgot' && 'Request a password reset link.', authMode === 'reset' && 'Set a new password using your reset token.', authMode === 'invite' && (inviteResolution === 'existing_user_ready'
@@ -941,7 +1092,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
941
1092
  ? (invitePasswordRequired ? 'Create password' : 'Password')
942
1093
  : 'Password'), autoComplete: authMode === 'register' || authMode === 'reset' || (authMode === 'invite' && invitePasswordRequired)
943
1094
  ? 'new-password'
944
- : 'current-password', "data-testid": "auth-password-input", onChange: (event) => setLoginPassword(event.target.value) })] })), authMode === 'verify' && (_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Verification token" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: verificationToken, placeholder: "Verification token", autoComplete: "one-time-code", "data-testid": "auth-verification-token-input", onChange: (event) => setVerificationToken(event.target.value) })] })), authMode === 'reset' && (_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Reset token" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: resetToken, placeholder: "Reset token", autoComplete: "one-time-code", "data-testid": "auth-reset-token-input", onChange: (event) => setResetToken(event.target.value) })] })), authMode === 'invite' && (_jsxs(_Fragment, { children: [_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Invite token" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: inviteToken, placeholder: "Invite token", "data-testid": "auth-invite-token-input", onChange: (event) => setInviteToken(event.target.value) })] }), inviteEmail && (_jsxs("p", { className: authStyles.loginSubtitle, children: ["Invite for: ", _jsx("strong", { children: inviteEmail }), inviteWorkspaceId ? ` · Workspace: ${inviteWorkspaceId}` : ''] }))] })), loginNotice && _jsx("p", { className: authStyles.loginSubtitle, children: loginNotice }), loginError && _jsx("p", { className: authStyles.loginError, children: loginError }), authMode === 'login' && loginErrorCode === 'EMAIL_NOT_VERIFIED' && loginEmail.trim() && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: async () => {
1095
+ : 'current-password', "data-testid": "auth-password-input", onChange: (event) => setLoginPassword(event.target.value) })] })), (authMode === 'register' || (authMode === 'invite' && invitePasswordRequired)) && (_jsx(_Fragment, { children: _jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Confirm password" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "password", value: loginPasswordConfirm, placeholder: "Confirm password", autoComplete: "new-password", "data-testid": "auth-confirm-password-input", onChange: (event) => setLoginPasswordConfirm(event.target.value) })] }) })), (authMode === 'register' || (authMode === 'invite' && invitePasswordRequired)) && (_jsx("p", { className: authStyles.loginSubtitle, children: registerPasswordGuidance.join(' ') })), authMode === 'verify' && (_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Verification token" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: verificationToken, placeholder: "Verification token", autoComplete: "one-time-code", "data-testid": "auth-verification-token-input", onChange: (event) => setVerificationToken(event.target.value) })] })), authMode === 'reset' && (_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Reset token" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: resetToken, placeholder: "Reset token", autoComplete: "one-time-code", "data-testid": "auth-reset-token-input", onChange: (event) => setResetToken(event.target.value) })] })), authMode === 'invite' && (_jsxs(_Fragment, { children: [_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Invite token" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: inviteToken, placeholder: "Invite token", "data-testid": "auth-invite-token-input", onChange: (event) => setInviteToken(event.target.value) })] }), inviteEmail && (_jsxs("p", { className: authStyles.loginSubtitle, children: ["Invite for: ", _jsx("strong", { children: inviteEmail }), inviteWorkspaceId ? ` · Workspace: ${inviteWorkspaceId}` : ''] }))] })), loginNotice && _jsx("p", { className: authStyles.loginSubtitle, children: loginNotice }), loginError && _jsx("p", { className: authStyles.loginError, children: loginError }), authMode === 'login' && loginErrorCode === 'EMAIL_NOT_VERIFIED' && loginEmail.trim() && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: async () => {
945
1096
  setLoginBusy(true);
946
1097
  setLoginNotice(null);
947
1098
  const sent = await requestEmailVerification(loginEmail);
@@ -968,6 +1119,24 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
968
1119
  setLoginBusy(false);
969
1120
  return;
970
1121
  }
1122
+ if (authMode === 'register') {
1123
+ const validation = validatePasswordPolicy(loginPassword, {
1124
+ email: loginEmail,
1125
+ displayName: loginDisplayName
1126
+ });
1127
+ if (!validation.ok) {
1128
+ setLoginError(validation.message || 'Password does not meet the password policy.');
1129
+ setLoginErrorCode(validation.code || null);
1130
+ setLoginBusy(false);
1131
+ return;
1132
+ }
1133
+ if (loginPassword !== loginPasswordConfirm) {
1134
+ setLoginError('Passwords do not match.');
1135
+ setLoginErrorCode('PASSWORD_CONFIRMATION_MISMATCH');
1136
+ setLoginBusy(false);
1137
+ return;
1138
+ }
1139
+ }
971
1140
  let result = { success: false };
972
1141
  if (authMode === 'login') {
973
1142
  result = await loginWithCredentials(loginEmail, loginPassword);
@@ -1060,6 +1229,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1060
1229
  : 'Account created. Check your email for verification instructions.');
1061
1230
  }
1062
1231
  else {
1232
+ setCommercialOnboardingRedirectActive(commercialOnboardingGate);
1063
1233
  setPendingPostAuthRedirect({
1064
1234
  path: postRegistrationPath,
1065
1235
  workspaceSetupRequired: Boolean(result.workspaceSetupRequired),
@@ -1071,6 +1241,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1071
1241
  await retryBootstrapChecks();
1072
1242
  const commercialOnboardingGate = pendingVerificationCommercialState === 'pending_plan_selection'
1073
1243
  || pendingVerificationCommercialState === 'checkout_pending';
1244
+ setCommercialOnboardingRedirectActive(commercialOnboardingGate);
1074
1245
  setPendingPostAuthRedirect({
1075
1246
  path: pendingVerificationRedirectPath || nextPath,
1076
1247
  workspaceSetupRequired: pendingVerificationWorkspaceSetupRequired,
@@ -1102,6 +1273,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1102
1273
  setAuthMode('invite');
1103
1274
  setInviteResolution('existing_user_ready');
1104
1275
  setLoginPassword('');
1276
+ setLoginPasswordConfirm('');
1105
1277
  setLoginNotice('Signed in. Review the invite details to continue.');
1106
1278
  setLoginError(null);
1107
1279
  setLoginErrorCode(null);
@@ -1113,6 +1285,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1113
1285
  }
1114
1286
  setInviteResolution('existing_user_signed_out');
1115
1287
  setLoginPassword('');
1288
+ setLoginPasswordConfirm('');
1116
1289
  setLoginNotice(normalizedInviteEmail
1117
1290
  ? `Signed in, but this invite is for ${inviteEmail}. Sign in with that account to continue.`
1118
1291
  : 'Signed in, but this invite requires the invited account. Sign in with that account to continue.');
@@ -1132,6 +1305,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1132
1305
  if (inviteToken.trim()) {
1133
1306
  setAuthMode('invite');
1134
1307
  setLoginPassword('');
1308
+ setLoginPasswordConfirm('');
1135
1309
  setLoginNotice('Signed in. Review the invite details to continue.');
1136
1310
  setLoginBusy(false);
1137
1311
  return;
@@ -1144,12 +1318,14 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1144
1318
  setLoginEmail('');
1145
1319
  setLoginDisplayName('');
1146
1320
  setLoginPassword('');
1321
+ setLoginPasswordConfirm('');
1147
1322
  navigate(nextPath, { replace: true });
1148
1323
  }
1149
1324
  else {
1150
1325
  setLoginEmail('');
1151
1326
  setLoginDisplayName('');
1152
1327
  setLoginPassword('');
1328
+ setLoginPasswordConfirm('');
1153
1329
  navigate(nextPath, { replace: true });
1154
1330
  }
1155
1331
  setLoginBusy(false);
@@ -1162,7 +1338,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1162
1338
  ? 'Reset Password'
1163
1339
  : (inviteResolution === 'existing_user_signed_out'
1164
1340
  ? 'Sign In to Continue'
1165
- : (invitePasswordRequired ? 'Create Account and Join' : 'Join Workspace'))) }) }), authMode === 'register' && (_jsxs("p", { className: authStyles.registerConsent, children: ["By creating an account, you agree to the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/terms", target: "_blank", rel: "noopener noreferrer", children: "Terms of Service" }), ' ', "and acknowledge the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/privacy", target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }), "."] })), _jsxs("div", { className: authStyles.authSecondaryActions, role: "group", "aria-label": "Authentication navigation", children: [directRegistrationEnabled && (authMode === 'login' || authMode === 'register') && (_jsxs("p", { className: authStyles.authModeSwitch, children: [authMode === 'login' ? 'Need an account?' : 'Already have an account?', ' ', _jsx("button", { className: authStyles.authModeSwitchLink, disabled: loginBusy, "data-testid": "auth-switch-mode-button", onClick: () => {
1341
+ : (invitePasswordRequired ? 'Create Account and Join' : 'Join Workspace'))) }) }), (authMode === 'login' || authMode === 'register') && availableAuthProviders.length > 0 && (_jsxs("div", { className: authStyles.oauthProviders, children: [_jsx("div", { className: authStyles.oauthDivider, children: _jsx("span", { children: "or continue with" }) }), _jsxs("div", { className: authStyles.oauthButtons, children: [availableAuthProviders.includes('google') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('google', location.pathname !== '/login' ? location.pathname : '/'), "aria-label": "Continue with Google", children: "Google" })), availableAuthProviders.includes('github') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('github', location.pathname !== '/login' ? location.pathname : '/'), "aria-label": "Continue with GitHub", children: "GitHub" })), availableAuthProviders.includes('apple') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('apple', location.pathname !== '/login' ? location.pathname : '/'), "aria-label": "Continue with Apple", children: "Apple" }))] })] })), authMode === 'invite' && inviteResolution === 'new_user' && inviteOAuthProviders.length > 0 && (_jsxs("div", { className: authStyles.oauthProviders, children: [_jsx("div", { className: authStyles.oauthDivider, children: _jsx("span", { children: "or join with" }) }), _jsxs("div", { className: authStyles.oauthButtons, children: [inviteOAuthProviders.includes('google') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('google', '/', inviteToken), "aria-label": "Join with Google", children: "Google" })), inviteOAuthProviders.includes('github') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('github', '/', inviteToken), "aria-label": "Join with GitHub", children: "GitHub" })), inviteOAuthProviders.includes('apple') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('apple', '/', inviteToken), "aria-label": "Join with Apple", children: "Apple" }))] })] })), authMode === 'register' && (_jsxs("p", { className: authStyles.registerConsent, children: ["By creating an account, you agree to the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/terms", target: "_blank", rel: "noopener noreferrer", children: "Terms of Service" }), ' ', "and acknowledge the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/privacy", target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }), "."] })), _jsxs("div", { className: authStyles.authSecondaryActions, role: "group", "aria-label": "Authentication navigation", children: [directRegistrationEnabled && (authMode === 'login' || authMode === 'register') && (_jsxs("p", { className: authStyles.authModeSwitch, children: [authMode === 'login' ? 'Need an account?' : 'Already have an account?', ' ', _jsx("button", { className: authStyles.authModeSwitchLink, disabled: loginBusy, "data-testid": "auth-switch-mode-button", onClick: () => {
1166
1342
  setLoginError(null);
1167
1343
  setLoginErrorCode(null);
1168
1344
  setLoginNotice(null);
@@ -1185,18 +1361,15 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
1185
1361
  setLoginBusy(false);
1186
1362
  }, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' })), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, "data-testid": "auth-return-sign-in-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('login'); }, children: authMode === 'verify' ? 'Back to Sign In' : 'Sign In' }), directRegistrationEnabled && authMode !== 'verify' && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, "data-testid": "auth-return-register-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('register'); }, children: "Register" })), authMode === 'reset' && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, "data-testid": "auth-return-forgot-password-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }))] }))] })] })] }) }) }));
1187
1363
  }
1188
- if (shouldForceLogin && !isLoginRoute) {
1364
+ if (shellRenderState === 'login-redirect') {
1189
1365
  return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, children: _jsxs("div", { className: authStyles.loginCard, children: [_jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsx("h1", { className: authStyles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: authStyles.loginSubtitle, children: "Redirecting to sign in..." })] }) }) }));
1190
1366
  }
1191
- if (isComingSoonRoute && shouldForceComingSoon) {
1367
+ if (shellRenderState === 'coming-soon') {
1192
1368
  return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, style: {
1193
1369
  backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
1194
1370
  }, children: _jsxs("div", { className: authStyles.loginCard, children: [_jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsx("h1", { className: authStyles.loginTitle, children: "Private Beta" })] }), _jsx("p", { className: authStyles.loginSubtitle, children: "You are signed in, but your account is not in the beta allowlist yet." }), _jsx("p", { className: authStyles.loginSubtitle, children: "You will see the full app as soon as beta access is enabled." }), _jsx("button", { className: styles.cancelBtn, onClick: async () => { await taskforceState.logout(); navigate('/login', { replace: true }); }, children: "Sign Out" })] }) }) }));
1195
1371
  }
1196
- const showGuidedWorkspaceSetup = isCreateWorkspaceIntent
1197
- || (isSetupRoute && Boolean(activeCloudWorkspaceImport))
1198
- || (isSetupRoute && setupGateActive && (hasSetupReadError || needsGlobalSetup || needsWorkspaceSetup));
1199
- if (showGuidedWorkspaceSetup) {
1372
+ if (shellRenderState === 'guided-setup') {
1200
1373
  const isError = !isCreateWorkspaceIntent && (hasSetupReadError || setupStep === 'error');
1201
1374
  const isGlobal = !isCreateWorkspaceIntent && !isError && (needsGlobalSetup || setupStep === 'global');
1202
1375
  const heading = isError