@taskforcehq/taskforce 0.3.305 → 0.3.306
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.
- package/dist/Taskforce.module.css +295 -89
- package/dist/TaskforceCore.js +215 -43
- package/dist/TaskforceCore.test.js +433 -28
- package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/assets/fonts/Noir_medium.woff2 +0 -0
- package/dist/assets/fonts/Noir_regular.woff2 +0 -0
- package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/compat/workspaceSyncCompat.js +46 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +549 -0
- package/dist/components/features/AgentsModule.d.ts +10 -1
- package/dist/components/features/AgentsModule.js +260 -15
- package/dist/components/features/AgentsModule.test.js +255 -5
- package/dist/components/features/DocumentViewer.d.ts +5 -1
- package/dist/components/features/DocumentViewer.js +60 -3
- package/dist/components/features/DocumentWorkspace.js +1 -1
- package/dist/components/features/DocumentWorkspace.test.js +33 -0
- package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
- package/dist/components/task/TaskCard.js +19 -28
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskForm.js +85 -90
- package/dist/components/task/TaskForm.test.js +110 -8
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +94 -13
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +70 -14
- package/dist/components/views/PlanComparisonPage.test.js +238 -0
- package/dist/components/views/PlansPage.js +127 -36
- package/dist/components/views/PlansPage.test.js +294 -12
- package/dist/components/views/StandaloneLayout.js +283 -533
- package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
- package/dist/components/views/panels/PlanningDrawer.js +18 -11
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +141 -0
- package/dist/components/views/planningScope.d.ts +20 -0
- package/dist/components/views/planningScope.js +25 -0
- package/dist/components/views/planningScope.test.d.ts +1 -0
- package/dist/components/views/planningScope.test.js +60 -0
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
- package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
- package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
- package/dist/core/AiProfileService.d.ts +39 -2
- package/dist/core/AiProfileService.js +639 -73
- package/dist/core/AiProfileService.test.js +19 -1
- package/dist/core/AiProfiles.test.js +566 -7
- package/dist/core/AttachmentLinkService.js +57 -15
- package/dist/core/AuthIdentityService.d.ts +107 -0
- package/dist/core/AuthIdentityService.js +284 -0
- package/dist/core/AuthTokenService.d.ts +4 -0
- package/dist/core/AuthTokenService.js +34 -6
- package/dist/core/AuthTokenService.test.js +3 -3
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +115 -6
- package/dist/core/PlanEntitlementService.d.ts +23 -2
- package/dist/core/PlanEntitlementService.js +343 -57
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +35 -2
- package/dist/core/PlanningEntities.test.js +52 -0
- package/dist/core/SignupMonetizationSettings.test.js +199 -27
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +42 -42
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/Taskforce.d.ts +225 -14
- package/dist/core/Taskforce.js +765 -192
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
- package/dist/core/WorkspaceLifecycleService.js +0 -5
- package/dist/core/WorkspacePermissions.test.js +25 -1
- package/dist/core/WorkspacePlanMode.test.js +117 -16
- package/dist/core/shared.d.ts +1 -1
- package/dist/core/shared.js +5 -1
- package/dist/core/types.d.ts +68 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
- package/dist/hooks/sync/bootstrap.js +2 -0
- package/dist/hooks/sync/controlPlane.d.ts +37 -0
- package/dist/hooks/sync/controlPlane.js +78 -0
- package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
- package/dist/hooks/sync/controlPlane.test.js +121 -0
- package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
- package/dist/hooks/sync/lifecyclePolicy.js +93 -0
- package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
- package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +10 -1
- package/dist/hooks/sync/orchestratorShared.js +68 -47
- package/dist/hooks/sync/orchestratorShared.test.js +50 -1
- package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
- package/dist/hooks/sync/pullLifecycle.js +24 -0
- package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
- package/dist/hooks/sync/pullLifecycle.test.js +80 -0
- package/dist/hooks/sync/recovery.d.ts +16 -2
- package/dist/hooks/sync/recovery.js +171 -53
- package/dist/hooks/sync/recovery.test.d.ts +1 -0
- package/dist/hooks/sync/recovery.test.js +292 -0
- package/dist/hooks/sync/transfers.d.ts +15 -3
- package/dist/hooks/sync/transfers.js +179 -62
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +396 -0
- package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
- package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
- package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
- package/dist/hooks/sync/useSyncStatusActions.js +88 -0
- package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
- package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
- package/dist/hooks/sync/useSyncStatusControls.js +60 -0
- package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
- package/dist/hooks/useSyncOrchestrator.js +359 -178
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskforce.d.ts +60 -2
- package/dist/hooks/useTaskforce.js +549 -240
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2380 -212
- package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.js +6 -1
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
- package/dist/localization/locales/en-US.d.ts +0 -1
- package/dist/localization/locales/en-US.js +0 -1
- package/dist/localization/locales/es-419.js +0 -1
- package/dist/localization/locales/pt-BR.js +0 -1
- package/dist/mcp/documentAssetRegistrar.js +3 -3
- package/dist/mcp/runtime.d.ts +2 -0
- package/dist/mcp/runtime.js +131 -64
- package/dist/mcp/runtime.test.js +291 -12
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +171 -61
- package/dist/migrations/taskSchemaMigrations.test.js +15 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/dist/resources/templates/workflows/collaborate.yaml +1 -1
- package/dist/resources/templates/workflows/evaluate.yaml +2 -2
- package/dist/resources/templates/workflows/plan.yaml +1 -1
- package/dist/resources/templates/workflows/review.yaml +2 -2
- package/dist/server/annotatedAttachmentsRoutes.test.js +3 -3
- package/dist/server/auth/providers/apple.d.ts +33 -0
- package/dist/server/auth/providers/apple.js +82 -0
- package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
- package/dist/server/auth/providers/appleClientSecret.js +65 -0
- package/dist/server/auth/providers/github.d.ts +26 -0
- package/dist/server/auth/providers/github.js +86 -0
- package/dist/server/auth/providers/google.d.ts +21 -0
- package/dist/server/auth/providers/google.js +56 -0
- package/dist/server/auth/providers/types.d.ts +21 -0
- package/dist/server/auth/providers/types.js +1 -0
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +6 -3
- package/dist/server/documentReviewRoutes.test.js +36 -3
- package/dist/server/index.cookieProxy.test.js +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +120 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +106 -3
- package/dist/server/routes/admin.d.ts +3 -0
- package/dist/server/routes/admin.js +272 -19
- package/dist/server/routes/auth.d.ts +15 -2
- package/dist/server/routes/auth.js +994 -57
- package/dist/server/routes/authSupport.d.ts +1 -1
- package/dist/server/routes/authSupport.js +1 -1
- package/dist/server/routes/billing.js +361 -35
- package/dist/server/routes/billing.test.js +592 -12
- package/dist/server/routes/documents.d.ts +1 -0
- package/dist/server/routes/documents.js +172 -70
- package/dist/server/routes/shared.d.ts +28 -2
- package/dist/server/routes/shared.js +69 -4
- package/dist/server/routes/sync.integration.test.js +437 -39
- package/dist/server/routes/sync.js +61 -605
- package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
- package/dist/server/routes/syncAuxRoutes.js +91 -0
- package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
- package/dist/server/routes/syncAuxRoutes.test.js +158 -0
- package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
- package/dist/server/routes/syncPullApplyRoutes.js +204 -0
- package/dist/server/routes/syncPushRoutes.d.ts +24 -0
- package/dist/server/routes/syncPushRoutes.js +212 -0
- package/dist/server/routes/syncRouteGuards.d.ts +36 -0
- package/dist/server/routes/syncRouteGuards.js +67 -0
- package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
- package/dist/server/routes/syncRouteGuards.test.js +94 -0
- package/dist/server/routes/syncRouteTypes.d.ts +13 -0
- package/dist/server/routes/syncRouteTypes.js +1 -0
- package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
- package/dist/server/routes/syncSnapshotRoutes.js +180 -0
- package/dist/server/routes/tasks.js +43 -1
- package/dist/server/routes/workspaces.js +36 -5
- package/dist/server/routes.js +60 -3
- package/dist/server/routes.test.js +1824 -171
- package/dist/services/workflowExportSnapshots.test.js +2 -0
- package/dist/shared/aiProfileSeatScope.d.ts +5 -0
- package/dist/shared/aiProfileSeatScope.js +21 -0
- package/dist/shared/passwordPolicy.d.ts +13 -0
- package/dist/shared/passwordPolicy.js +84 -0
- package/dist/shared/passwordPolicy.test.d.ts +1 -0
- package/dist/shared/passwordPolicy.test.js +34 -0
- package/dist/storage/workspaceAssetStore.d.ts +15 -3
- package/dist/storage/workspaceAssetStore.js +132 -44
- package/dist/storage/workspaceAssetStore.test.js +93 -6
- package/dist/styles/fonts.css +70 -0
- package/dist/sync/collaborationSyncPayload.d.ts +6 -1
- package/dist/sync/collaborationSyncPayload.js +17 -11
- package/dist/sync/collaborationSyncPayload.test.js +13 -1
- package/dist/sync/contentSyncState.d.ts +4 -8
- package/dist/sync/contentSyncState.js +17 -70
- package/dist/sync/syncApplyHandlers.d.ts +7 -0
- package/dist/sync/syncApplyHandlers.js +28 -13
- package/dist/sync/syncApplyHandlers.test.js +70 -3
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +44 -0
- package/dist/sync/syncResourceAdapters.js +77 -0
- package/dist/sync/syncService.d.ts +5 -0
- package/dist/sync/syncService.js +52 -0
- package/dist/sync/syncService.test.js +57 -3
- package/dist/sync/taskSyncChangeKey.d.ts +2 -0
- package/dist/sync/taskSyncChangeKey.js +143 -0
- package/dist/sync/taskSyncPayload.js +3 -8
- package/dist/sync/workspacePullFeed.js +4 -3
- package/dist/sync/workspacePullFeed.test.js +43 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +45 -0
- package/dist/sync/workspaceSyncModel.js +183 -28
- package/dist/sync/workspaceSyncModel.test.js +291 -12
- package/dist/sync/workspaceSyncState.d.ts +17 -0
- package/dist/sync/workspaceSyncState.js +2 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +17 -0
- package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BG6P_GVW.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
- package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
- package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +252 -0
- package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
- package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-9E6ParrY.js} +1 -1
- package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
- package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
- package/dist/ui/assets/PlansPage-CvfnMiWq.css +1 -0
- package/dist/ui/assets/PlansPage-DRXscYxH.js +1 -0
- package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
- package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
- package/dist/ui/assets/{TaskSettings-ln0aF7xc.js → TaskSettings-DZX4jk7e.js} +1 -1
- package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-BA7jcEpH.js} +1 -1
- package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
- package/dist/ui/assets/index-C6k75jr8.js +6 -0
- package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-DuEd_65c.js} +1 -1
- package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/ui/fonts/Noir_medium.otf +0 -0
- package/dist/ui/fonts/Noir_medium.woff2 +0 -0
- package/dist/ui/fonts/Noir_regular.otf +0 -0
- package/dist/ui/fonts/Noir_regular.woff2 +0 -0
- package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/assignees.d.ts +2 -0
- package/dist/utils/assignees.js +2 -0
- package/dist/utils/avatarUpload.d.ts +27 -0
- package/dist/utils/avatarUpload.js +132 -0
- package/dist/utils/avatarUpload.test.d.ts +1 -0
- package/dist/utils/avatarUpload.test.js +40 -0
- package/dist/utils/bootstrapTrace.d.ts +7 -0
- package/dist/utils/bootstrapTrace.js +29 -0
- package/dist/utils/commercialLifecyclePresentation.js +3 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/syncEventDetails.d.ts +3 -0
- package/dist/utils/syncEventDetails.js +64 -0
- package/dist/utils/syncEventDetails.test.d.ts +1 -0
- package/dist/utils/syncEventDetails.test.js +23 -0
- package/dist/utils/syncEventPresentation.d.ts +15 -0
- package/dist/utils/syncEventPresentation.js +129 -0
- package/dist/utils/syncEventPresentation.test.d.ts +1 -0
- package/dist/utils/syncEventPresentation.test.js +64 -0
- package/dist/utils/syncStatusPresentation.d.ts +72 -0
- package/dist/utils/syncStatusPresentation.js +217 -0
- package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
- package/dist/utils/syncStatusPresentation.test.js +164 -0
- package/dist/utils/taskActivity.d.ts +2 -0
- package/dist/utils/taskActivity.js +228 -22
- package/dist/utils/taskActivity.test.js +119 -8
- package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.js +68 -2
- package/dist/utils/workspaceSyncPresentation.test.js +36 -1
- package/package.json +3 -2
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- package/scripts/run-e2e-realtime.sh +17 -3
- package/scripts/run-smoke.sh +17 -5
- package/scripts/run-soak.sh +17 -5
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/src/resources/templates/workflows/collaborate.yaml +1 -1
- package/src/resources/templates/workflows/evaluate.yaml +2 -2
- package/src/resources/templates/workflows/plan.yaml +1 -1
- package/src/resources/templates/workflows/review.yaml +2 -2
- package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/index-C2-OXZV7.css +0 -1
- package/dist/ui/assets/index-DcSI5F86.js +0 -6
- package/scripts/migrate-planning-model.ts +0 -233
package/dist/TaskforceCore.js
CHANGED
|
@@ -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,
|
|
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
|
-
&&
|
|
248
|
+
&& bootstrapState.authPending
|
|
242
249
|
&& !isLoginRoute
|
|
243
250
|
&& !isSetupRoute
|
|
244
251
|
&& !isPricingRoute
|
|
@@ -266,23 +273,47 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
266
273
|
const needsWorkspaceSetup = workspaceLifecycle.needsWorkspaceSetup;
|
|
267
274
|
const hasSetupReadError = workspaceLifecycle.hasSetupReadError;
|
|
268
275
|
const shouldHoldForSetupBootstrap = mode !== 'widget'
|
|
269
|
-
&&
|
|
276
|
+
&& bootstrapState.auth.resolved
|
|
270
277
|
&& !shouldForceLogin
|
|
271
278
|
&& !shouldForceComingSoon
|
|
272
279
|
&& !isPricingRoute
|
|
273
280
|
&& !isPlansRoute
|
|
274
281
|
&& !isPlansScreen
|
|
275
|
-
&&
|
|
282
|
+
&& bootstrapState.appPending
|
|
276
283
|
&& (isSetupRoute || runtimeMode === 'cloud' || isLikelyCloudAppHost);
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
const shouldHoldForCommercialOnboardingRedirect = runtimeMode === 'cloud'
|
|
285
|
+
&& commercialOnboardingRedirectActive
|
|
286
|
+
&& !isPlansScreen;
|
|
287
|
+
const bootstrapSubtitle = bootstrapState.subtitle;
|
|
288
|
+
const showGuidedWorkspaceSetup = isCreateWorkspaceIntent
|
|
289
|
+
|| (isSetupRoute && Boolean(activeCloudWorkspaceImport))
|
|
290
|
+
|| (isSetupRoute && setupGateActive && (hasSetupReadError || needsGlobalSetup || needsWorkspaceSetup));
|
|
291
|
+
const shellRenderState = useMemo(() => {
|
|
292
|
+
if (shouldHoldForAuthBootstrap)
|
|
293
|
+
return 'auth-bootstrap';
|
|
294
|
+
if (shouldHoldForCommercialOnboardingRedirect)
|
|
295
|
+
return 'app-bootstrap';
|
|
296
|
+
if (shouldHoldForSetupBootstrap)
|
|
297
|
+
return 'app-bootstrap';
|
|
298
|
+
if (isLoginRoute)
|
|
299
|
+
return 'login';
|
|
300
|
+
if (shouldForceLogin && !isLoginRoute)
|
|
301
|
+
return 'login-redirect';
|
|
302
|
+
if (isComingSoonRoute && shouldForceComingSoon)
|
|
303
|
+
return 'coming-soon';
|
|
304
|
+
if (showGuidedWorkspaceSetup)
|
|
305
|
+
return 'guided-setup';
|
|
306
|
+
return 'app';
|
|
307
|
+
}, [
|
|
308
|
+
isComingSoonRoute,
|
|
309
|
+
isLoginRoute,
|
|
310
|
+
shouldForceComingSoon,
|
|
311
|
+
shouldForceLogin,
|
|
312
|
+
shouldHoldForCommercialOnboardingRedirect,
|
|
313
|
+
shouldHoldForAuthBootstrap,
|
|
314
|
+
shouldHoldForSetupBootstrap,
|
|
315
|
+
showGuidedWorkspaceSetup
|
|
316
|
+
]);
|
|
286
317
|
const isPlaceholderWorkspaceName = useCallback((name, workspaceId, _description) => {
|
|
287
318
|
const normalizedName = String(name || '').trim().toLowerCase();
|
|
288
319
|
const normalizedWorkspaceId = String(workspaceId || '').trim().toLowerCase();
|
|
@@ -299,7 +330,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
299
330
|
setSetupModeChoice(modeValue);
|
|
300
331
|
}, [setupState?.mode]);
|
|
301
332
|
useEffect(() => {
|
|
302
|
-
if (runtimeMode !== 'cloud' || !isAuthenticated
|
|
333
|
+
if (runtimeMode !== 'cloud' || !isAuthenticated) {
|
|
334
|
+
setAccountAccessGate(null);
|
|
335
|
+
setAccountAccessGateResolved(false);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (!authSessionResolved) {
|
|
303
339
|
setAccountAccessGate(null);
|
|
304
340
|
setAccountAccessGateResolved(false);
|
|
305
341
|
return;
|
|
@@ -637,27 +673,95 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
637
673
|
setPendingVerificationRedirectPath(null);
|
|
638
674
|
}, [authMode, isLoginRoute, loginRouteMode]);
|
|
639
675
|
useEffect(() => {
|
|
640
|
-
if (
|
|
676
|
+
if (authMode === 'register')
|
|
641
677
|
return;
|
|
642
|
-
|
|
678
|
+
setLoginPasswordConfirm('');
|
|
679
|
+
}, [authMode]);
|
|
680
|
+
useEffect(() => {
|
|
681
|
+
if (!pendingPostAuthRedirect || !isAuthenticated)
|
|
682
|
+
return;
|
|
683
|
+
if (!pendingPostAuthRedirect.commercialOnboardingGate && (!authSessionResolved || cloudAccountAccessPending)) {
|
|
643
684
|
return;
|
|
644
685
|
}
|
|
645
|
-
|
|
646
|
-
|
|
686
|
+
const destination = !pendingPostAuthRedirect.commercialOnboardingGate && pendingPostAuthRedirect.workspaceSetupRequired
|
|
687
|
+
? resolveWorkspaceSetupPath()
|
|
688
|
+
: pendingPostAuthRedirect.path;
|
|
689
|
+
const currentRoute = `${location.pathname}${location.search}${location.hash || ''}`;
|
|
690
|
+
if (currentRoute !== destination) {
|
|
691
|
+
navigate(destination, { replace: true });
|
|
647
692
|
}
|
|
648
|
-
|
|
649
|
-
|
|
693
|
+
}, [
|
|
694
|
+
authSessionResolved,
|
|
695
|
+
cloudAccountAccessPending,
|
|
696
|
+
isAuthenticated,
|
|
697
|
+
location.hash,
|
|
698
|
+
location.pathname,
|
|
699
|
+
location.search,
|
|
700
|
+
navigate,
|
|
701
|
+
pendingPostAuthRedirect,
|
|
702
|
+
resolveWorkspaceSetupPath
|
|
703
|
+
]);
|
|
704
|
+
useEffect(() => {
|
|
705
|
+
if (!commercialOnboardingRedirectActive)
|
|
706
|
+
return;
|
|
707
|
+
if (!authSessionResolved) {
|
|
708
|
+
return;
|
|
650
709
|
}
|
|
710
|
+
if (!isAuthenticated) {
|
|
711
|
+
setCommercialOnboardingRedirectActive(false);
|
|
712
|
+
setPendingPostAuthRedirect(null);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (accountAccessGateResolved && accountAccessGate?.canAccessApp === true) {
|
|
716
|
+
setLoginEmail('');
|
|
717
|
+
setLoginDisplayName('');
|
|
718
|
+
setLoginPassword('');
|
|
719
|
+
setLoginPasswordConfirm('');
|
|
720
|
+
setPendingPostAuthRedirect(null);
|
|
721
|
+
setCommercialOnboardingRedirectActive(false);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const destination = pendingPostAuthRedirect?.commercialOnboardingGate
|
|
725
|
+
? pendingPostAuthRedirect.path
|
|
726
|
+
: planSelectionPath;
|
|
727
|
+
const currentRoute = `${location.pathname}${location.search}${location.hash || ''}`;
|
|
728
|
+
if (currentRoute !== destination) {
|
|
729
|
+
navigate(destination, { replace: true });
|
|
730
|
+
}
|
|
731
|
+
}, [
|
|
732
|
+
accountAccessGate?.canAccessApp,
|
|
733
|
+
accountAccessGateResolved,
|
|
734
|
+
authSessionResolved,
|
|
735
|
+
commercialOnboardingRedirectActive,
|
|
736
|
+
isAuthenticated,
|
|
737
|
+
location.hash,
|
|
738
|
+
location.pathname,
|
|
739
|
+
location.search,
|
|
740
|
+
navigate,
|
|
741
|
+
pendingPostAuthRedirect,
|
|
742
|
+
planSelectionPath
|
|
743
|
+
]);
|
|
744
|
+
useEffect(() => {
|
|
745
|
+
if (!pendingPostAuthRedirect || !isAuthenticated)
|
|
746
|
+
return;
|
|
747
|
+
const destination = !pendingPostAuthRedirect.commercialOnboardingGate && pendingPostAuthRedirect.workspaceSetupRequired
|
|
748
|
+
? resolveWorkspaceSetupPath()
|
|
749
|
+
: pendingPostAuthRedirect.path;
|
|
750
|
+
const currentRoute = `${location.pathname}${location.search}${location.hash || ''}`;
|
|
751
|
+
if (currentRoute !== destination)
|
|
752
|
+
return;
|
|
753
|
+
if (pendingPostAuthRedirect.commercialOnboardingGate)
|
|
754
|
+
return;
|
|
651
755
|
setLoginEmail('');
|
|
652
756
|
setLoginDisplayName('');
|
|
653
757
|
setLoginPassword('');
|
|
758
|
+
setLoginPasswordConfirm('');
|
|
654
759
|
setPendingPostAuthRedirect(null);
|
|
655
760
|
}, [
|
|
656
|
-
|
|
657
|
-
|
|
761
|
+
location.hash,
|
|
762
|
+
location.pathname,
|
|
763
|
+
location.search,
|
|
658
764
|
isAuthenticated,
|
|
659
|
-
isLoginRoute,
|
|
660
|
-
navigate,
|
|
661
765
|
pendingPostAuthRedirect,
|
|
662
766
|
resolveWorkspaceSetupPath,
|
|
663
767
|
runtimeMode
|
|
@@ -679,6 +783,9 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
679
783
|
setInviteEmail(inspected.email || null);
|
|
680
784
|
setInviteWorkspaceId(inspected.workspaceId || null);
|
|
681
785
|
setInvitePasswordRequired(inspected.passwordRequired === true);
|
|
786
|
+
// Capture OAuth providers available for invite-claim (pending_setup only)
|
|
787
|
+
const oauthMethods = (inspected.availableMethods || []).filter(m => m === 'google' || m === 'github' || m === 'apple');
|
|
788
|
+
setInviteOAuthProviders(inspected.inviteeState === 'pending_setup' ? oauthMethods : []);
|
|
682
789
|
const inviteMatchesAuthenticatedUser = Boolean(isAuthenticated
|
|
683
790
|
&& authUserEmail
|
|
684
791
|
&& inspected.email
|
|
@@ -704,6 +811,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
704
811
|
setInviteWorkspaceId(null);
|
|
705
812
|
setInviteResolution('invalid');
|
|
706
813
|
setInvitePasswordRequired(false);
|
|
814
|
+
setInviteOAuthProviders([]);
|
|
707
815
|
setLoginError(formatAuthError(inspected));
|
|
708
816
|
setLoginErrorCode(inspected.code || inspected.state || null);
|
|
709
817
|
}
|
|
@@ -730,6 +838,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
730
838
|
const resetCooldownSeconds = Math.max(0, Math.ceil((resetCooldownUntil - cooldownNow) / 1000));
|
|
731
839
|
const verifyCooldownActive = verifyCooldownSeconds > 0;
|
|
732
840
|
const resetCooldownActive = resetCooldownSeconds > 0;
|
|
841
|
+
const registerPasswordGuidance = useMemo(() => getPasswordPolicyGuidance(), []);
|
|
733
842
|
const formatAuthError = (result) => {
|
|
734
843
|
const message = result.error || 'Request failed.';
|
|
735
844
|
const code = result.code || result.state;
|
|
@@ -756,7 +865,15 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
756
865
|
useEffect(() => {
|
|
757
866
|
if (mode === 'widget')
|
|
758
867
|
return;
|
|
759
|
-
if (
|
|
868
|
+
if (isLoginRoute && loginBusy) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const shouldBypassWorkspacePendingForAccessGate = runtimeMode === 'cloud'
|
|
872
|
+
&& isAuthenticated
|
|
873
|
+
&& accountAccessGateResolved
|
|
874
|
+
&& accountAccessGate?.canAccessApp === false
|
|
875
|
+
&& accountAccessGate?.canAccessPlans !== false;
|
|
876
|
+
if (bootstrapState.workspace.pending && !shouldBypassWorkspacePendingForAccessGate)
|
|
760
877
|
return;
|
|
761
878
|
if (shouldForceComingSoon) {
|
|
762
879
|
if (!isComingSoonRoute)
|
|
@@ -775,10 +892,11 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
775
892
|
&& isAuthenticated
|
|
776
893
|
&& !shouldStayOnInviteRoute
|
|
777
894
|
&& (Boolean(pendingPostAuthRedirect)
|
|
778
|
-
||
|
|
895
|
+
|| bootstrapState.workspace.pending
|
|
779
896
|
|| authMode === 'register'
|
|
780
897
|
|| authMode === 'verify'
|
|
781
|
-
||
|
|
898
|
+
|| !bootstrapState.config.loaded
|
|
899
|
+
|| cloudAccountAccessPending);
|
|
782
900
|
if (shouldDelayAuthenticatedLoginRedirect) {
|
|
783
901
|
return;
|
|
784
902
|
}
|
|
@@ -796,6 +914,23 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
796
914
|
if (isLoginRoute && !isAuthenticated) {
|
|
797
915
|
return;
|
|
798
916
|
}
|
|
917
|
+
if (pendingPostAuthRedirect && isAuthenticated) {
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const shouldHoldAuthenticatedAuthRoute = isLoginRoute
|
|
921
|
+
&& isAuthenticated
|
|
922
|
+
&& (authMode === 'register'
|
|
923
|
+
|| authMode === 'verify'
|
|
924
|
+
|| (authMode === 'invite' && inviteToken.trim().length > 0));
|
|
925
|
+
if (shouldHoldAuthenticatedAuthRoute) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
if (commercialOnboardingRedirectActive) {
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
if (isPlansScreen) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
799
934
|
if (shouldForceAccountAccessGate) {
|
|
800
935
|
if (!isPlansScreen) {
|
|
801
936
|
const gate = encodeURIComponent(String(accountAccessGate?.gate || 'plan_selection_required'));
|
|
@@ -812,6 +947,16 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
812
947
|
}
|
|
813
948
|
return;
|
|
814
949
|
}
|
|
950
|
+
if (isPlansScreen && cloudAccountAccessPending) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
if (isPlansScreen
|
|
954
|
+
&& runtimeMode === 'cloud'
|
|
955
|
+
&& accountAccessGateResolved
|
|
956
|
+
&& accountAccessGate?.canAccessApp === false
|
|
957
|
+
&& accountAccessGate?.canAccessPlans !== false) {
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
815
960
|
if (setupGateActive) {
|
|
816
961
|
if (hasSetupReadError) {
|
|
817
962
|
if (!isSetupRoute || setupStep !== 'error') {
|
|
@@ -849,9 +994,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
849
994
|
isComingSoonRoute,
|
|
850
995
|
isPlansRoute,
|
|
851
996
|
isPlansScreen,
|
|
997
|
+
accountAccessGate,
|
|
852
998
|
accountAccessGate?.gate,
|
|
853
999
|
accountAccessGateResolved,
|
|
854
1000
|
authMode,
|
|
1001
|
+
commercialOnboardingRedirectActive,
|
|
1002
|
+
cloudAccountAccessPending,
|
|
855
1003
|
setupGateActive,
|
|
856
1004
|
setupState,
|
|
857
1005
|
hasSetupReadError,
|
|
@@ -860,9 +1008,11 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
860
1008
|
needsGlobalSetup,
|
|
861
1009
|
needsWorkspaceSetup,
|
|
862
1010
|
setupStep,
|
|
863
|
-
|
|
864
|
-
configLoaded,
|
|
1011
|
+
bootstrapState,
|
|
865
1012
|
runtimeMode,
|
|
1013
|
+
loginBusy,
|
|
1014
|
+
isAuthenticated,
|
|
1015
|
+
accountAccessGateResolved,
|
|
866
1016
|
inviteToken,
|
|
867
1017
|
location.pathname,
|
|
868
1018
|
location.search,
|
|
@@ -877,7 +1027,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
877
1027
|
return;
|
|
878
1028
|
if (runtimeMode !== 'local')
|
|
879
1029
|
return;
|
|
880
|
-
if (!
|
|
1030
|
+
if (!bootstrapState.config.loaded)
|
|
881
1031
|
return;
|
|
882
1032
|
if (isLoginRoute || isSetupRoute)
|
|
883
1033
|
return;
|
|
@@ -885,7 +1035,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
885
1035
|
if (!workspaceId || workspaceId === 'default') {
|
|
886
1036
|
navigate('/setup?step=workspace', { replace: true });
|
|
887
1037
|
}
|
|
888
|
-
}, [mode, runtimeMode,
|
|
1038
|
+
}, [mode, runtimeMode, bootstrapState.config.loaded, isLoginRoute, isSetupRoute, currentWorkspaceId, navigate]);
|
|
889
1039
|
const handleRetryBootstrap = useCallback(async () => {
|
|
890
1040
|
setBootstrapRetryBusy(true);
|
|
891
1041
|
try {
|
|
@@ -913,13 +1063,13 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
913
1063
|
params.set('screen', 'plans');
|
|
914
1064
|
return _jsx(Navigate, { to: `/?${params.toString()}${location.hash || ''}`, replace: true });
|
|
915
1065
|
}
|
|
916
|
-
if (
|
|
1066
|
+
if (shellRenderState === 'auth-bootstrap') {
|
|
917
1067
|
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
1068
|
}
|
|
919
|
-
if (
|
|
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 }),
|
|
1069
|
+
if (shellRenderState === 'app-bootstrap') {
|
|
1070
|
+
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
1071
|
}
|
|
922
|
-
if (
|
|
1072
|
+
if (shellRenderState === 'login') {
|
|
923
1073
|
return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, style: {
|
|
924
1074
|
backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
|
|
925
1075
|
}, 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 +1091,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
941
1091
|
? (invitePasswordRequired ? 'Create password' : 'Password')
|
|
942
1092
|
: 'Password'), autoComplete: authMode === 'register' || authMode === 'reset' || (authMode === 'invite' && invitePasswordRequired)
|
|
943
1093
|
? '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 () => {
|
|
1094
|
+
: '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
1095
|
setLoginBusy(true);
|
|
946
1096
|
setLoginNotice(null);
|
|
947
1097
|
const sent = await requestEmailVerification(loginEmail);
|
|
@@ -968,6 +1118,24 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
968
1118
|
setLoginBusy(false);
|
|
969
1119
|
return;
|
|
970
1120
|
}
|
|
1121
|
+
if (authMode === 'register') {
|
|
1122
|
+
const validation = validatePasswordPolicy(loginPassword, {
|
|
1123
|
+
email: loginEmail,
|
|
1124
|
+
displayName: loginDisplayName
|
|
1125
|
+
});
|
|
1126
|
+
if (!validation.ok) {
|
|
1127
|
+
setLoginError(validation.message || 'Password does not meet the password policy.');
|
|
1128
|
+
setLoginErrorCode(validation.code || null);
|
|
1129
|
+
setLoginBusy(false);
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
if (loginPassword !== loginPasswordConfirm) {
|
|
1133
|
+
setLoginError('Passwords do not match.');
|
|
1134
|
+
setLoginErrorCode('PASSWORD_CONFIRMATION_MISMATCH');
|
|
1135
|
+
setLoginBusy(false);
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
971
1139
|
let result = { success: false };
|
|
972
1140
|
if (authMode === 'login') {
|
|
973
1141
|
result = await loginWithCredentials(loginEmail, loginPassword);
|
|
@@ -1060,6 +1228,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1060
1228
|
: 'Account created. Check your email for verification instructions.');
|
|
1061
1229
|
}
|
|
1062
1230
|
else {
|
|
1231
|
+
setCommercialOnboardingRedirectActive(commercialOnboardingGate);
|
|
1063
1232
|
setPendingPostAuthRedirect({
|
|
1064
1233
|
path: postRegistrationPath,
|
|
1065
1234
|
workspaceSetupRequired: Boolean(result.workspaceSetupRequired),
|
|
@@ -1071,6 +1240,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1071
1240
|
await retryBootstrapChecks();
|
|
1072
1241
|
const commercialOnboardingGate = pendingVerificationCommercialState === 'pending_plan_selection'
|
|
1073
1242
|
|| pendingVerificationCommercialState === 'checkout_pending';
|
|
1243
|
+
setCommercialOnboardingRedirectActive(commercialOnboardingGate);
|
|
1074
1244
|
setPendingPostAuthRedirect({
|
|
1075
1245
|
path: pendingVerificationRedirectPath || nextPath,
|
|
1076
1246
|
workspaceSetupRequired: pendingVerificationWorkspaceSetupRequired,
|
|
@@ -1102,6 +1272,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1102
1272
|
setAuthMode('invite');
|
|
1103
1273
|
setInviteResolution('existing_user_ready');
|
|
1104
1274
|
setLoginPassword('');
|
|
1275
|
+
setLoginPasswordConfirm('');
|
|
1105
1276
|
setLoginNotice('Signed in. Review the invite details to continue.');
|
|
1106
1277
|
setLoginError(null);
|
|
1107
1278
|
setLoginErrorCode(null);
|
|
@@ -1113,6 +1284,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1113
1284
|
}
|
|
1114
1285
|
setInviteResolution('existing_user_signed_out');
|
|
1115
1286
|
setLoginPassword('');
|
|
1287
|
+
setLoginPasswordConfirm('');
|
|
1116
1288
|
setLoginNotice(normalizedInviteEmail
|
|
1117
1289
|
? `Signed in, but this invite is for ${inviteEmail}. Sign in with that account to continue.`
|
|
1118
1290
|
: 'Signed in, but this invite requires the invited account. Sign in with that account to continue.');
|
|
@@ -1132,6 +1304,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1132
1304
|
if (inviteToken.trim()) {
|
|
1133
1305
|
setAuthMode('invite');
|
|
1134
1306
|
setLoginPassword('');
|
|
1307
|
+
setLoginPasswordConfirm('');
|
|
1135
1308
|
setLoginNotice('Signed in. Review the invite details to continue.');
|
|
1136
1309
|
setLoginBusy(false);
|
|
1137
1310
|
return;
|
|
@@ -1144,12 +1317,14 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1144
1317
|
setLoginEmail('');
|
|
1145
1318
|
setLoginDisplayName('');
|
|
1146
1319
|
setLoginPassword('');
|
|
1320
|
+
setLoginPasswordConfirm('');
|
|
1147
1321
|
navigate(nextPath, { replace: true });
|
|
1148
1322
|
}
|
|
1149
1323
|
else {
|
|
1150
1324
|
setLoginEmail('');
|
|
1151
1325
|
setLoginDisplayName('');
|
|
1152
1326
|
setLoginPassword('');
|
|
1327
|
+
setLoginPasswordConfirm('');
|
|
1153
1328
|
navigate(nextPath, { replace: true });
|
|
1154
1329
|
}
|
|
1155
1330
|
setLoginBusy(false);
|
|
@@ -1162,7 +1337,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1162
1337
|
? 'Reset Password'
|
|
1163
1338
|
: (inviteResolution === 'existing_user_signed_out'
|
|
1164
1339
|
? '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: () => {
|
|
1340
|
+
: (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
1341
|
setLoginError(null);
|
|
1167
1342
|
setLoginErrorCode(null);
|
|
1168
1343
|
setLoginNotice(null);
|
|
@@ -1185,18 +1360,15 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
1185
1360
|
setLoginBusy(false);
|
|
1186
1361
|
}, 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
1362
|
}
|
|
1188
|
-
if (
|
|
1363
|
+
if (shellRenderState === 'login-redirect') {
|
|
1189
1364
|
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
1365
|
}
|
|
1191
|
-
if (
|
|
1366
|
+
if (shellRenderState === 'coming-soon') {
|
|
1192
1367
|
return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, style: {
|
|
1193
1368
|
backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
|
|
1194
1369
|
}, 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
1370
|
}
|
|
1196
|
-
|
|
1197
|
-
|| (isSetupRoute && Boolean(activeCloudWorkspaceImport))
|
|
1198
|
-
|| (isSetupRoute && setupGateActive && (hasSetupReadError || needsGlobalSetup || needsWorkspaceSetup));
|
|
1199
|
-
if (showGuidedWorkspaceSetup) {
|
|
1371
|
+
if (shellRenderState === 'guided-setup') {
|
|
1200
1372
|
const isError = !isCreateWorkspaceIntent && (hasSetupReadError || setupStep === 'error');
|
|
1201
1373
|
const isGlobal = !isCreateWorkspaceIntent && !isError && (needsGlobalSetup || setupStep === 'global');
|
|
1202
1374
|
const heading = isError
|