@taskforcehq/taskforce 0.3.328 → 0.3.329
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 +233 -34
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +147 -40
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +7 -31
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/config/envSchema.js +12 -0
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/Taskforce.d.ts +62 -2
- package/dist/core/Taskforce.js +635 -32
- package/dist/core/types.d.ts +6 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useTaskData.d.ts +10 -1
- package/dist/hooks/useTaskData.js +216 -7
- package/dist/hooks/useTaskMutations.d.ts +10 -2
- package/dist/hooks/useTaskMutations.js +223 -43
- package/dist/hooks/useTaskforce.d.ts +37 -9
- package/dist/hooks/useTaskforce.js +349 -39
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/documentAssetRegistrar.js +44 -35
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/runtime.js +172 -42
- package/dist/mcp/taskPlanningRegistrar.js +41 -38
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/migrations/taskSchemaMigrations.js +12 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +12 -13
- package/dist/runtime/appGates.js +29 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +15 -3
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +9 -1
- package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.js +1 -0
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.js +118 -16
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +9 -2
- package/dist/server/routes/localService.js +2 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncV3FeedRoutes.js +18 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +10 -0
- package/dist/server/routes/tasks.js +103 -11
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +112 -0
- package/dist/services/codexAppServerModelGateway.js +438 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
- package/dist/services/taskforceAgentMcpBridge.js +23 -3
- package/dist/shared/taskforceAgentDefinition.js +7 -1
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +30 -1
- package/dist/storage/postgresAdapter.d.ts +20 -3
- package/dist/storage/postgresAdapter.js +106 -14
- package/dist/storage/postgresWorker.js +13 -4
- package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +7 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +25 -8
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
- package/dist/sync/syncService.d.ts +2 -0
- package/dist/sync/syncService.js +4 -1
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +11 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
- package/dist/sync/v3/syncDurabilityStore.d.ts +7 -0
- package/dist/sync/v3/syncDurabilityStore.js +31 -11
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
- package/dist/sync/v3/taskChecklistMutationService.js +4 -0
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
- package/dist/sync/v3/taskStatusMutationService.js +4 -0
- package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
- package/dist/sync/v3/workflowAssignmentSync.js +3 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -1
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +30 -18
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +98 -47
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +58 -21
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +3 -0
- package/dist/sync/workspaceRepair.js +67 -6
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/{AiIdentityRosterCard-MZs7lVED.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-C8Rztyal.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Cj3c7X9y.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-B5uvzems.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-BVFvCB5R.js} +1 -1
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
- package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
- package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
- package/dist/ui/assets/{TaskforceAgentsModule-BazdUwxZ.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DEr5di_r.js} +1 -1
- package/dist/ui/assets/index-I5zhdtgt.js +7 -0
- package/dist/ui/assets/index-VRFsx3wz.css +1 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-D9Lpw-j4.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/package.json +16 -4
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
package/dist/TaskforceCore.js
CHANGED
|
@@ -17,6 +17,7 @@ import { isLightThemeFamily } from './utils/theme';
|
|
|
17
17
|
import { Cloud, LaptopMinimal } from 'lucide-react';
|
|
18
18
|
import { getPasswordPolicyGuidance, validatePasswordPolicy } from './shared/passwordPolicy';
|
|
19
19
|
import { TASK_DEEP_LINK_QUERY_KEYS } from './shared/taskDeepLinks';
|
|
20
|
+
import { PasswordInput } from './components/ui/PasswordInput';
|
|
20
21
|
function isDebugModeEnabled() {
|
|
21
22
|
const runtimeOverride = globalThis.__DEBUG_MODE__;
|
|
22
23
|
if (typeof runtimeOverride === 'boolean')
|
|
@@ -732,10 +733,10 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, initialActivityEn
|
|
|
732
733
|
setPendingVerificationRedirectPath(null);
|
|
733
734
|
}, [authMode, isLoginRoute, loginRouteMode]);
|
|
734
735
|
useEffect(() => {
|
|
735
|
-
if (authMode === 'register')
|
|
736
|
+
if (authMode === 'register' || authMode === 'reset' || (authMode === 'invite' && invitePasswordRequired))
|
|
736
737
|
return;
|
|
737
738
|
setLoginPasswordConfirm('');
|
|
738
|
-
}, [authMode]);
|
|
739
|
+
}, [authMode, invitePasswordRequired]);
|
|
739
740
|
useEffect(() => {
|
|
740
741
|
if (!pendingPostAuthRedirect || !isAuthenticated)
|
|
741
742
|
return;
|
|
@@ -1155,10 +1156,234 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, initialActivityEn
|
|
|
1155
1156
|
if (shellRenderState === 'app-bootstrap') {
|
|
1156
1157
|
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" }))] }))] }) }) }));
|
|
1157
1158
|
}
|
|
1159
|
+
const handleAuthSubmit = async () => {
|
|
1160
|
+
setLoginBusy(true);
|
|
1161
|
+
setLoginNotice(null);
|
|
1162
|
+
setLoginError(null);
|
|
1163
|
+
setLoginErrorCode(null);
|
|
1164
|
+
if (authMode === 'register' && !loginDisplayName.trim()) {
|
|
1165
|
+
setLoginError('Display name is required.');
|
|
1166
|
+
setLoginBusy(false);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
if (authMode === 'register' || authMode === 'reset' || (authMode === 'invite' && invitePasswordRequired)) {
|
|
1170
|
+
const validation = validatePasswordPolicy(loginPassword, {
|
|
1171
|
+
email: loginEmail,
|
|
1172
|
+
displayName: loginDisplayName
|
|
1173
|
+
});
|
|
1174
|
+
if (!validation.ok) {
|
|
1175
|
+
setLoginError(validation.message || 'Password does not meet the password policy.');
|
|
1176
|
+
setLoginErrorCode(validation.code || null);
|
|
1177
|
+
setLoginBusy(false);
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
if (loginPassword !== loginPasswordConfirm) {
|
|
1181
|
+
setLoginError('Passwords do not match.');
|
|
1182
|
+
setLoginErrorCode('PASSWORD_CONFIRMATION_MISMATCH');
|
|
1183
|
+
setLoginBusy(false);
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
let result = { success: false };
|
|
1188
|
+
if (authMode === 'login') {
|
|
1189
|
+
result = await loginWithCredentials(loginEmail, loginPassword);
|
|
1190
|
+
}
|
|
1191
|
+
else if (authMode === 'register') {
|
|
1192
|
+
result = await registerWithCredentials(loginEmail, loginPassword, {
|
|
1193
|
+
displayName: loginDisplayName,
|
|
1194
|
+
planId: selectedSignupPlanId || undefined,
|
|
1195
|
+
planVersionId: selectedSignupPlanVersionId || undefined,
|
|
1196
|
+
interval: selectedSignupInterval || undefined
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
else if (authMode === 'verify') {
|
|
1200
|
+
result = await confirmEmailVerification(verificationToken);
|
|
1201
|
+
}
|
|
1202
|
+
else if (authMode === 'forgot') {
|
|
1203
|
+
result = await requestPasswordReset(loginEmail);
|
|
1204
|
+
}
|
|
1205
|
+
else if (authMode === 'reset') {
|
|
1206
|
+
result = await confirmPasswordReset(resetToken, loginPassword);
|
|
1207
|
+
}
|
|
1208
|
+
else if (authMode === 'invite') {
|
|
1209
|
+
if (inviteResolution === 'existing_user_signed_out') {
|
|
1210
|
+
result = await loginWithCredentials(loginEmail, loginPassword);
|
|
1211
|
+
}
|
|
1212
|
+
else {
|
|
1213
|
+
result = invitePasswordRequired
|
|
1214
|
+
? await acceptInviteWithToken(inviteToken, loginPassword)
|
|
1215
|
+
: await joinInviteWithToken(inviteToken);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
if (!result.success) {
|
|
1219
|
+
if (authMode === 'register'
|
|
1220
|
+
&& (result.code === 'SIGNUP_PLAN_NOT_ENABLED'
|
|
1221
|
+
|| result.code === 'SIGNUP_PLAN_VERSION_NOT_FOUND'
|
|
1222
|
+
|| result.code === 'SIGNUP_PLAN_VERSION_REQUIRED')) {
|
|
1223
|
+
navigate(planSelectionPath, { replace: true });
|
|
1224
|
+
setLoginBusy(false);
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
setLoginError(formatAuthError(result));
|
|
1228
|
+
setLoginErrorCode(result.code || null);
|
|
1229
|
+
if (authMode === 'login' && (result.code === 'WORKSPACE_NOT_FOUND' || result.code === 'WORKSPACE_ID_REQUIRED')) {
|
|
1230
|
+
navigate('/setup?step=workspace', { replace: true });
|
|
1231
|
+
setLoginBusy(false);
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
if (authMode === 'login' && result.code === 'EMAIL_NOT_VERIFIED' && loginEmail.trim()) {
|
|
1235
|
+
const sent = await requestEmailVerification(loginEmail);
|
|
1236
|
+
if (sent.success) {
|
|
1237
|
+
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
1238
|
+
setLoginMode('verify');
|
|
1239
|
+
if (sent.verificationToken)
|
|
1240
|
+
setVerificationToken(sent.verificationToken);
|
|
1241
|
+
setLoginNotice(buildVerificationRequestNotice({
|
|
1242
|
+
...sent,
|
|
1243
|
+
intro: 'If that account exists and still needs verification, we sent an email.'
|
|
1244
|
+
}));
|
|
1245
|
+
setLoginError(null);
|
|
1246
|
+
setLoginErrorCode(null);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
if (authMode === 'register' && result.code === 'EMAIL_ALREADY_EXISTS_UNVERIFIED' && loginEmail.trim()) {
|
|
1250
|
+
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
1251
|
+
setLoginMode('verify');
|
|
1252
|
+
if (result.verificationToken)
|
|
1253
|
+
setVerificationToken(result.verificationToken);
|
|
1254
|
+
setLoginNotice(result.emailSent === false
|
|
1255
|
+
? `This email already has an unverified account, but verification email delivery failed. ${result.emailError || 'Try Resend Verification again.'}`
|
|
1256
|
+
: 'This email already has an unverified account. Check your email for verification instructions.');
|
|
1257
|
+
setLoginError(null);
|
|
1258
|
+
setLoginErrorCode(null);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
else if (authMode === 'register') {
|
|
1262
|
+
const postRegistrationPath = resolvePostRegistrationPath(result);
|
|
1263
|
+
const commercialOnboardingGate = hasCommercialOnboardingGate(result);
|
|
1264
|
+
if (result.verificationRequired) {
|
|
1265
|
+
setPendingVerificationWorkspaceSetupRequired(Boolean(result.workspaceSetupRequired));
|
|
1266
|
+
setPendingVerificationCommercialState(commercialOnboardingGate
|
|
1267
|
+
? String(result.commercialState || '').trim() || (result.planSelectionRequired ? 'pending_plan_selection' : 'checkout_pending')
|
|
1268
|
+
: null);
|
|
1269
|
+
setPendingVerificationRedirectPath(postRegistrationPath);
|
|
1270
|
+
if (result.verificationToken)
|
|
1271
|
+
setVerificationToken(result.verificationToken);
|
|
1272
|
+
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
1273
|
+
setLoginMode('verify');
|
|
1274
|
+
setLoginNotice(result.emailSent === false
|
|
1275
|
+
? `Account created, but verification email failed to send. ${result.emailError || 'Try Resend Verification again.'}`
|
|
1276
|
+
: 'Account created. Check your email for verification instructions.');
|
|
1277
|
+
}
|
|
1278
|
+
else {
|
|
1279
|
+
setCommercialOnboardingRedirectActive(commercialOnboardingGate);
|
|
1280
|
+
setPendingPostAuthRedirect({
|
|
1281
|
+
path: postRegistrationPath,
|
|
1282
|
+
workspaceSetupRequired: Boolean(result.workspaceSetupRequired),
|
|
1283
|
+
commercialOnboardingGate
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
else if (authMode === 'verify') {
|
|
1288
|
+
await retryBootstrapChecks();
|
|
1289
|
+
const commercialOnboardingGate = pendingVerificationCommercialState === 'pending_plan_selection'
|
|
1290
|
+
|| pendingVerificationCommercialState === 'checkout_pending';
|
|
1291
|
+
setCommercialOnboardingRedirectActive(commercialOnboardingGate);
|
|
1292
|
+
setPendingPostAuthRedirect({
|
|
1293
|
+
path: pendingVerificationRedirectPath || nextTarget,
|
|
1294
|
+
workspaceSetupRequired: pendingVerificationWorkspaceSetupRequired,
|
|
1295
|
+
commercialOnboardingGate
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
else if (authMode === 'forgot') {
|
|
1299
|
+
const passwordResetDeliveryFailed = result.deliveryAttempted === true && result.emailSent === false;
|
|
1300
|
+
if (result.resetToken)
|
|
1301
|
+
setResetToken(result.resetToken);
|
|
1302
|
+
setLoginNotice(buildPasswordResetNotice(result));
|
|
1303
|
+
if (!passwordResetDeliveryFailed) {
|
|
1304
|
+
setResetCooldownUntil(Date.now() + 30_000);
|
|
1305
|
+
setLoginMode('reset');
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
else if (authMode === 'reset') {
|
|
1309
|
+
setLoginMode('login');
|
|
1310
|
+
setLoginNotice('Password updated. Sign in with your new password.');
|
|
1311
|
+
}
|
|
1312
|
+
else if (authMode === 'invite') {
|
|
1313
|
+
if (inviteResolution === 'existing_user_signed_out') {
|
|
1314
|
+
const normalizedInviteEmail = String(inviteEmail || '').trim().toLowerCase();
|
|
1315
|
+
const normalizedLoginEmail = loginEmail.trim().toLowerCase();
|
|
1316
|
+
// Make the invite flow deterministically join-ready as soon as
|
|
1317
|
+
// the invited account signs in successfully, instead of waiting
|
|
1318
|
+
// for a later invite inspection effect to catch up.
|
|
1319
|
+
if (normalizedInviteEmail && normalizedLoginEmail === normalizedInviteEmail) {
|
|
1320
|
+
setAuthMode('invite');
|
|
1321
|
+
setInviteResolution('existing_user_ready');
|
|
1322
|
+
setLoginPassword('');
|
|
1323
|
+
setLoginPasswordConfirm('');
|
|
1324
|
+
setLoginNotice('Signed in. Review the invite details to continue.');
|
|
1325
|
+
setLoginError(null);
|
|
1326
|
+
setLoginErrorCode(null);
|
|
1327
|
+
setLoginBusy(false);
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
if (normalizedInviteEmail) {
|
|
1331
|
+
setLoginEmail(inviteEmail || '');
|
|
1332
|
+
}
|
|
1333
|
+
setInviteResolution('existing_user_signed_out');
|
|
1334
|
+
setLoginPassword('');
|
|
1335
|
+
setLoginPasswordConfirm('');
|
|
1336
|
+
setLoginNotice(normalizedInviteEmail
|
|
1337
|
+
? `Signed in, but this invite is for ${inviteEmail}. Sign in with that account to continue.`
|
|
1338
|
+
: 'Signed in, but this invite requires the invited account. Sign in with that account to continue.');
|
|
1339
|
+
setLoginError('Sign in with the invited account to join this workspace.');
|
|
1340
|
+
setLoginErrorCode('INVITE_ACCOUNT_MISMATCH');
|
|
1341
|
+
setLoginBusy(false);
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
if (result.workspaceSetupRequired) {
|
|
1345
|
+
navigate(resolveWorkspaceSetupPath(), { replace: true });
|
|
1346
|
+
setLoginBusy(false);
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
navigateToPostAuthTarget(nextTarget, { replace: true });
|
|
1350
|
+
}
|
|
1351
|
+
else if (authMode === 'login') {
|
|
1352
|
+
if (inviteToken.trim()) {
|
|
1353
|
+
setAuthMode('invite');
|
|
1354
|
+
setLoginPassword('');
|
|
1355
|
+
setLoginPasswordConfirm('');
|
|
1356
|
+
setLoginNotice('Signed in. Review the invite details to continue.');
|
|
1357
|
+
setLoginBusy(false);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
if (result.workspaceSetupRequired) {
|
|
1361
|
+
navigate(resolveWorkspaceSetupPath(), { replace: true });
|
|
1362
|
+
setLoginBusy(false);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
setLoginEmail('');
|
|
1366
|
+
setLoginDisplayName('');
|
|
1367
|
+
setLoginPassword('');
|
|
1368
|
+
setLoginPasswordConfirm('');
|
|
1369
|
+
navigateToPostAuthTarget(nextTarget, { replace: true });
|
|
1370
|
+
}
|
|
1371
|
+
else {
|
|
1372
|
+
setLoginEmail('');
|
|
1373
|
+
setLoginDisplayName('');
|
|
1374
|
+
setLoginPassword('');
|
|
1375
|
+
setLoginPasswordConfirm('');
|
|
1376
|
+
navigateToPostAuthTarget(nextTarget, { replace: true });
|
|
1377
|
+
}
|
|
1378
|
+
setLoginBusy(false);
|
|
1379
|
+
};
|
|
1158
1380
|
if (shellRenderState === 'login') {
|
|
1159
1381
|
return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, style: {
|
|
1160
1382
|
backgroundImage: `linear-gradient(rgba(15, 15, 26, 0.88), rgba(15, 15, 26, 0.9)), url(${taskforceBg})`
|
|
1161
|
-
}, children: _jsxs("
|
|
1383
|
+
}, children: _jsxs("form", { className: authStyles.loginCard, onSubmit: (event) => {
|
|
1384
|
+
event.preventDefault();
|
|
1385
|
+
void handleAuthSubmit();
|
|
1386
|
+
}, children: [!isCloudRuntime && !shouldForceLogin && (_jsx("button", { type: "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'
|
|
1162
1387
|
? `You've been invited to join ${inviteWorkspaceId || 'this workspace'}.`
|
|
1163
1388
|
: inviteResolution === 'existing_user_signed_out'
|
|
1164
1389
|
? 'Sign in to join this workspace.'
|
|
@@ -1169,15 +1394,17 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, initialActivityEn
|
|
|
1169
1394
|
|| (authMode === 'invite' && inviteResolution === 'existing_user_signed_out')) && (_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Email" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "email", value: loginEmail, placeholder: "Email", autoComplete: "email", "data-testid": "auth-email-input", onChange: (event) => setLoginEmail(event.target.value) })] })), authMode === 'register' && (_jsxs("label", { className: authStyles.loginField, children: [_jsx("span", { className: authStyles.loginFieldLabel, children: "Display name" }), _jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: loginDisplayName, placeholder: "Display name", autoComplete: "nickname", "data-testid": "auth-display-name-input", onChange: (event) => setLoginDisplayName(event.target.value) })] })), (authMode === 'login'
|
|
1170
1395
|
|| authMode === 'register'
|
|
1171
1396
|
|| authMode === 'reset'
|
|
1172
|
-
|| (authMode === 'invite' && (invitePasswordRequired || inviteResolution === 'existing_user_signed_out'))) && (_jsxs("
|
|
1397
|
+
|| (authMode === 'invite' && (invitePasswordRequired || inviteResolution === 'existing_user_signed_out'))) && (_jsxs("div", { className: authStyles.loginField, children: [_jsx("label", { className: authStyles.loginFieldLabel, htmlFor: "auth-password-input", children: authMode === 'reset'
|
|
1173
1398
|
? 'New password'
|
|
1174
|
-
: (authMode === 'invite' && invitePasswordRequired ? 'Create password' : 'Password') }), _jsx("input",
|
|
1399
|
+
: (authMode === 'invite' && invitePasswordRequired ? 'Create password' : 'Password') }), _jsx(PasswordInput, { id: "auth-password-input", className: `${styles.input} ${authStyles.loginInput}`, value: loginPassword, placeholder: authMode === 'reset'
|
|
1175
1400
|
? 'New password'
|
|
1176
1401
|
: (authMode === 'invite'
|
|
1177
1402
|
? (invitePasswordRequired ? 'Create password' : 'Password')
|
|
1178
1403
|
: 'Password'), autoComplete: authMode === 'register' || authMode === 'reset' || (authMode === 'invite' && invitePasswordRequired)
|
|
1179
1404
|
? 'new-password'
|
|
1180
|
-
: 'current-password',
|
|
1405
|
+
: 'current-password', visibilityLabel: authMode === 'reset'
|
|
1406
|
+
? 'new password'
|
|
1407
|
+
: (authMode === 'invite' && invitePasswordRequired ? 'new password' : 'password'), "data-testid": "auth-password-input", visibilityToggleTestId: "auth-password-visibility-toggle", onChange: (event) => setLoginPassword(event.target.value) }, `${authMode}-${invitePasswordRequired ? 'new' : 'current'}`)] })), (authMode === 'register' || authMode === 'reset' || (authMode === 'invite' && invitePasswordRequired)) && (_jsxs("div", { className: authStyles.loginField, children: [_jsx("label", { className: authStyles.loginFieldLabel, htmlFor: "auth-confirm-password-input", children: "Confirm password" }), _jsx(PasswordInput, { id: "auth-confirm-password-input", className: `${styles.input} ${authStyles.loginInput}`, value: loginPasswordConfirm, placeholder: "Confirm password", autoComplete: "new-password", visibilityLabel: "confirm password", "data-testid": "auth-confirm-password-input", visibilityToggleTestId: "auth-confirm-password-visibility-toggle", onChange: (event) => setLoginPasswordConfirm(event.target.value) }, `${authMode}-confirm`)] })), (authMode === 'register' || authMode === 'reset' || (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, role: "alert", children: loginError }), authMode === 'login' && loginErrorCode === 'EMAIL_NOT_VERIFIED' && loginEmail.trim() && (_jsx("button", { type: "button", className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: async () => {
|
|
1181
1408
|
setLoginBusy(true);
|
|
1182
1409
|
setLoginNotice(null);
|
|
1183
1410
|
const sent = await requestEmailVerification(loginEmail);
|
|
@@ -1194,227 +1421,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, initialActivityEn
|
|
|
1194
1421
|
setLoginError(formatAuthError(sent));
|
|
1195
1422
|
}
|
|
1196
1423
|
setLoginBusy(false);
|
|
1197
|
-
}, children: verifyCooldownActive ? `Resend in ${verifyCooldownSeconds}s` : 'Resend Verification Email' })), _jsx("div", { className: authStyles.authPrimaryActions, role: "group", "aria-label": "Primary authentication action", children: _jsx("button", { className: `${styles.submitBtn} ${authStyles.loginPrimaryBtn}`, disabled: loginBusy || (authMode === 'forgot' && resetCooldownActive), "data-testid": "auth-submit-button",
|
|
1198
|
-
setLoginBusy(true);
|
|
1199
|
-
setLoginNotice(null);
|
|
1200
|
-
setLoginError(null);
|
|
1201
|
-
setLoginErrorCode(null);
|
|
1202
|
-
if (authMode === 'register' && !loginDisplayName.trim()) {
|
|
1203
|
-
setLoginError('Display name is required.');
|
|
1204
|
-
setLoginBusy(false);
|
|
1205
|
-
return;
|
|
1206
|
-
}
|
|
1207
|
-
if (authMode === 'register') {
|
|
1208
|
-
const validation = validatePasswordPolicy(loginPassword, {
|
|
1209
|
-
email: loginEmail,
|
|
1210
|
-
displayName: loginDisplayName
|
|
1211
|
-
});
|
|
1212
|
-
if (!validation.ok) {
|
|
1213
|
-
setLoginError(validation.message || 'Password does not meet the password policy.');
|
|
1214
|
-
setLoginErrorCode(validation.code || null);
|
|
1215
|
-
setLoginBusy(false);
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
if (loginPassword !== loginPasswordConfirm) {
|
|
1219
|
-
setLoginError('Passwords do not match.');
|
|
1220
|
-
setLoginErrorCode('PASSWORD_CONFIRMATION_MISMATCH');
|
|
1221
|
-
setLoginBusy(false);
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
let result = { success: false };
|
|
1226
|
-
if (authMode === 'login') {
|
|
1227
|
-
result = await loginWithCredentials(loginEmail, loginPassword);
|
|
1228
|
-
}
|
|
1229
|
-
else if (authMode === 'register') {
|
|
1230
|
-
result = await registerWithCredentials(loginEmail, loginPassword, {
|
|
1231
|
-
displayName: loginDisplayName,
|
|
1232
|
-
planId: selectedSignupPlanId || undefined,
|
|
1233
|
-
planVersionId: selectedSignupPlanVersionId || undefined,
|
|
1234
|
-
interval: selectedSignupInterval || undefined
|
|
1235
|
-
});
|
|
1236
|
-
}
|
|
1237
|
-
else if (authMode === 'verify') {
|
|
1238
|
-
result = await confirmEmailVerification(verificationToken);
|
|
1239
|
-
}
|
|
1240
|
-
else if (authMode === 'forgot') {
|
|
1241
|
-
result = await requestPasswordReset(loginEmail);
|
|
1242
|
-
}
|
|
1243
|
-
else if (authMode === 'reset') {
|
|
1244
|
-
result = await confirmPasswordReset(resetToken, loginPassword);
|
|
1245
|
-
}
|
|
1246
|
-
else if (authMode === 'invite') {
|
|
1247
|
-
if (inviteResolution === 'existing_user_signed_out') {
|
|
1248
|
-
result = await loginWithCredentials(loginEmail, loginPassword);
|
|
1249
|
-
}
|
|
1250
|
-
else {
|
|
1251
|
-
result = invitePasswordRequired
|
|
1252
|
-
? await acceptInviteWithToken(inviteToken, loginPassword)
|
|
1253
|
-
: await joinInviteWithToken(inviteToken);
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
if (!result.success) {
|
|
1257
|
-
if (authMode === 'register'
|
|
1258
|
-
&& (result.code === 'SIGNUP_PLAN_NOT_ENABLED'
|
|
1259
|
-
|| result.code === 'SIGNUP_PLAN_VERSION_NOT_FOUND'
|
|
1260
|
-
|| result.code === 'SIGNUP_PLAN_VERSION_REQUIRED')) {
|
|
1261
|
-
navigate(planSelectionPath, { replace: true });
|
|
1262
|
-
setLoginBusy(false);
|
|
1263
|
-
return;
|
|
1264
|
-
}
|
|
1265
|
-
setLoginError(formatAuthError(result));
|
|
1266
|
-
setLoginErrorCode(result.code || null);
|
|
1267
|
-
if (authMode === 'login' && (result.code === 'WORKSPACE_NOT_FOUND' || result.code === 'WORKSPACE_ID_REQUIRED')) {
|
|
1268
|
-
navigate('/setup?step=workspace', { replace: true });
|
|
1269
|
-
setLoginBusy(false);
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
if (authMode === 'login' && result.code === 'EMAIL_NOT_VERIFIED' && loginEmail.trim()) {
|
|
1273
|
-
const sent = await requestEmailVerification(loginEmail);
|
|
1274
|
-
if (sent.success) {
|
|
1275
|
-
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
1276
|
-
setLoginMode('verify');
|
|
1277
|
-
if (sent.verificationToken)
|
|
1278
|
-
setVerificationToken(sent.verificationToken);
|
|
1279
|
-
setLoginNotice(buildVerificationRequestNotice({
|
|
1280
|
-
...sent,
|
|
1281
|
-
intro: 'If that account exists and still needs verification, we sent an email.'
|
|
1282
|
-
}));
|
|
1283
|
-
setLoginError(null);
|
|
1284
|
-
setLoginErrorCode(null);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
if (authMode === 'register' && result.code === 'EMAIL_ALREADY_EXISTS_UNVERIFIED' && loginEmail.trim()) {
|
|
1288
|
-
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
1289
|
-
setLoginMode('verify');
|
|
1290
|
-
if (result.verificationToken)
|
|
1291
|
-
setVerificationToken(result.verificationToken);
|
|
1292
|
-
setLoginNotice(result.emailSent === false
|
|
1293
|
-
? `This email already has an unverified account, but verification email delivery failed. ${result.emailError || 'Try Resend Verification again.'}`
|
|
1294
|
-
: 'This email already has an unverified account. Check your email for verification instructions.');
|
|
1295
|
-
setLoginError(null);
|
|
1296
|
-
setLoginErrorCode(null);
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
else if (authMode === 'register') {
|
|
1300
|
-
const postRegistrationPath = resolvePostRegistrationPath(result);
|
|
1301
|
-
const commercialOnboardingGate = hasCommercialOnboardingGate(result);
|
|
1302
|
-
if (result.verificationRequired) {
|
|
1303
|
-
setPendingVerificationWorkspaceSetupRequired(Boolean(result.workspaceSetupRequired));
|
|
1304
|
-
setPendingVerificationCommercialState(commercialOnboardingGate
|
|
1305
|
-
? String(result.commercialState || '').trim() || (result.planSelectionRequired ? 'pending_plan_selection' : 'checkout_pending')
|
|
1306
|
-
: null);
|
|
1307
|
-
setPendingVerificationRedirectPath(postRegistrationPath);
|
|
1308
|
-
if (result.verificationToken)
|
|
1309
|
-
setVerificationToken(result.verificationToken);
|
|
1310
|
-
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
1311
|
-
setLoginMode('verify');
|
|
1312
|
-
setLoginNotice(result.emailSent === false
|
|
1313
|
-
? `Account created, but verification email failed to send. ${result.emailError || 'Try Resend Verification again.'}`
|
|
1314
|
-
: 'Account created. Check your email for verification instructions.');
|
|
1315
|
-
}
|
|
1316
|
-
else {
|
|
1317
|
-
setCommercialOnboardingRedirectActive(commercialOnboardingGate);
|
|
1318
|
-
setPendingPostAuthRedirect({
|
|
1319
|
-
path: postRegistrationPath,
|
|
1320
|
-
workspaceSetupRequired: Boolean(result.workspaceSetupRequired),
|
|
1321
|
-
commercialOnboardingGate
|
|
1322
|
-
});
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
else if (authMode === 'verify') {
|
|
1326
|
-
await retryBootstrapChecks();
|
|
1327
|
-
const commercialOnboardingGate = pendingVerificationCommercialState === 'pending_plan_selection'
|
|
1328
|
-
|| pendingVerificationCommercialState === 'checkout_pending';
|
|
1329
|
-
setCommercialOnboardingRedirectActive(commercialOnboardingGate);
|
|
1330
|
-
setPendingPostAuthRedirect({
|
|
1331
|
-
path: pendingVerificationRedirectPath || nextTarget,
|
|
1332
|
-
workspaceSetupRequired: pendingVerificationWorkspaceSetupRequired,
|
|
1333
|
-
commercialOnboardingGate
|
|
1334
|
-
});
|
|
1335
|
-
}
|
|
1336
|
-
else if (authMode === 'forgot') {
|
|
1337
|
-
const passwordResetDeliveryFailed = result.deliveryAttempted === true && result.emailSent === false;
|
|
1338
|
-
if (result.resetToken)
|
|
1339
|
-
setResetToken(result.resetToken);
|
|
1340
|
-
setLoginNotice(buildPasswordResetNotice(result));
|
|
1341
|
-
if (!passwordResetDeliveryFailed) {
|
|
1342
|
-
setResetCooldownUntil(Date.now() + 30_000);
|
|
1343
|
-
setLoginMode('reset');
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
else if (authMode === 'reset') {
|
|
1347
|
-
setLoginMode('login');
|
|
1348
|
-
setLoginNotice('Password updated. Sign in with your new password.');
|
|
1349
|
-
}
|
|
1350
|
-
else if (authMode === 'invite') {
|
|
1351
|
-
if (inviteResolution === 'existing_user_signed_out') {
|
|
1352
|
-
const normalizedInviteEmail = String(inviteEmail || '').trim().toLowerCase();
|
|
1353
|
-
const normalizedLoginEmail = loginEmail.trim().toLowerCase();
|
|
1354
|
-
// Make the invite flow deterministically join-ready as soon as
|
|
1355
|
-
// the invited account signs in successfully, instead of waiting
|
|
1356
|
-
// for a later invite inspection effect to catch up.
|
|
1357
|
-
if (normalizedInviteEmail && normalizedLoginEmail === normalizedInviteEmail) {
|
|
1358
|
-
setAuthMode('invite');
|
|
1359
|
-
setInviteResolution('existing_user_ready');
|
|
1360
|
-
setLoginPassword('');
|
|
1361
|
-
setLoginPasswordConfirm('');
|
|
1362
|
-
setLoginNotice('Signed in. Review the invite details to continue.');
|
|
1363
|
-
setLoginError(null);
|
|
1364
|
-
setLoginErrorCode(null);
|
|
1365
|
-
setLoginBusy(false);
|
|
1366
|
-
return;
|
|
1367
|
-
}
|
|
1368
|
-
if (normalizedInviteEmail) {
|
|
1369
|
-
setLoginEmail(inviteEmail || '');
|
|
1370
|
-
}
|
|
1371
|
-
setInviteResolution('existing_user_signed_out');
|
|
1372
|
-
setLoginPassword('');
|
|
1373
|
-
setLoginPasswordConfirm('');
|
|
1374
|
-
setLoginNotice(normalizedInviteEmail
|
|
1375
|
-
? `Signed in, but this invite is for ${inviteEmail}. Sign in with that account to continue.`
|
|
1376
|
-
: 'Signed in, but this invite requires the invited account. Sign in with that account to continue.');
|
|
1377
|
-
setLoginError('Sign in with the invited account to join this workspace.');
|
|
1378
|
-
setLoginErrorCode('INVITE_ACCOUNT_MISMATCH');
|
|
1379
|
-
setLoginBusy(false);
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
|
-
if (result.workspaceSetupRequired) {
|
|
1383
|
-
navigate(resolveWorkspaceSetupPath(), { replace: true });
|
|
1384
|
-
setLoginBusy(false);
|
|
1385
|
-
return;
|
|
1386
|
-
}
|
|
1387
|
-
navigateToPostAuthTarget(nextTarget, { replace: true });
|
|
1388
|
-
}
|
|
1389
|
-
else if (authMode === 'login') {
|
|
1390
|
-
if (inviteToken.trim()) {
|
|
1391
|
-
setAuthMode('invite');
|
|
1392
|
-
setLoginPassword('');
|
|
1393
|
-
setLoginPasswordConfirm('');
|
|
1394
|
-
setLoginNotice('Signed in. Review the invite details to continue.');
|
|
1395
|
-
setLoginBusy(false);
|
|
1396
|
-
return;
|
|
1397
|
-
}
|
|
1398
|
-
if (result.workspaceSetupRequired) {
|
|
1399
|
-
navigate(resolveWorkspaceSetupPath(), { replace: true });
|
|
1400
|
-
setLoginBusy(false);
|
|
1401
|
-
return;
|
|
1402
|
-
}
|
|
1403
|
-
setLoginEmail('');
|
|
1404
|
-
setLoginDisplayName('');
|
|
1405
|
-
setLoginPassword('');
|
|
1406
|
-
setLoginPasswordConfirm('');
|
|
1407
|
-
navigateToPostAuthTarget(nextTarget, { replace: true });
|
|
1408
|
-
}
|
|
1409
|
-
else {
|
|
1410
|
-
setLoginEmail('');
|
|
1411
|
-
setLoginDisplayName('');
|
|
1412
|
-
setLoginPassword('');
|
|
1413
|
-
setLoginPasswordConfirm('');
|
|
1414
|
-
navigateToPostAuthTarget(nextTarget, { replace: true });
|
|
1415
|
-
}
|
|
1416
|
-
setLoginBusy(false);
|
|
1417
|
-
}, children: loginBusy ? 'Working...' : (authMode === 'login' ? 'Sign In'
|
|
1424
|
+
}, children: verifyCooldownActive ? `Resend in ${verifyCooldownSeconds}s` : 'Resend Verification Email' })), _jsx("div", { className: authStyles.authPrimaryActions, role: "group", "aria-label": "Primary authentication action", children: _jsx("button", { type: "submit", className: `${styles.submitBtn} ${authStyles.loginPrimaryBtn}`, disabled: loginBusy || (authMode === 'forgot' && resetCooldownActive), "data-testid": "auth-submit-button", children: loginBusy ? 'Working...' : (authMode === 'login' ? 'Sign In'
|
|
1418
1425
|
: authMode === 'register' ? 'Create Account'
|
|
1419
1426
|
: authMode === 'verify' ? 'Verify Email'
|
|
1420
1427
|
: authMode === 'forgot'
|
|
@@ -1423,12 +1430,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, initialActivityEn
|
|
|
1423
1430
|
? 'Reset Password'
|
|
1424
1431
|
: (inviteResolution === 'existing_user_signed_out'
|
|
1425
1432
|
? 'Sign In to Continue'
|
|
1426
|
-
: (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', nextTarget), "aria-label": "Continue with Google", children: "Google" })), availableAuthProviders.includes('github') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('github', nextTarget), "aria-label": "Continue with GitHub", children: "GitHub" })), availableAuthProviders.includes('apple') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('apple', nextTarget), "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.ai/legal/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms of Service" }), ' ', "and acknowledge the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.ai/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: () => {
|
|
1433
|
+
: (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', nextTarget), "aria-label": "Continue with Google", children: "Google" })), availableAuthProviders.includes('github') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('github', nextTarget), "aria-label": "Continue with GitHub", children: "GitHub" })), availableAuthProviders.includes('apple') && (_jsx("button", { type: "button", className: authStyles.oauthButton, disabled: loginBusy, onClick: () => beginOAuthLogin('apple', nextTarget), "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.ai/legal/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms of Service" }), ' ', "and acknowledge the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.ai/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", { type: "button", className: authStyles.authModeSwitchLink, disabled: loginBusy, "data-testid": "auth-switch-mode-button", onClick: () => {
|
|
1427
1434
|
setLoginError(null);
|
|
1428
1435
|
setLoginErrorCode(null);
|
|
1429
1436
|
setLoginNotice(null);
|
|
1430
1437
|
setLoginMode(authMode === 'login' ? 'register' : 'login');
|
|
1431
|
-
}, children: authMode === 'login' ? 'Register' : 'Sign In' })] })), _jsxs("div", { className: authStyles.authModeLinks, children: [(authMode === 'login' || authMode === 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, "data-testid": "auth-forgot-password-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, "data-testid": "auth-resend-verification-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('verify'); }, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, "data-testid": "auth-accept-invite-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('invite'); }, children: "Accept Invite" })] })), (authMode !== 'login' && authMode !== 'register') && (_jsxs(_Fragment, { children: [authMode === 'verify' && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive || !loginEmail.trim(), "data-testid": "auth-resend-verification-button", onClick: async () => {
|
|
1438
|
+
}, children: authMode === 'login' ? 'Register' : 'Sign In' })] })), _jsxs("div", { className: authStyles.authModeLinks, children: [(authMode === 'login' || authMode === 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, "data-testid": "auth-forgot-password-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }), _jsx("button", { type: "button", className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, "data-testid": "auth-resend-verification-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('verify'); }, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' }), _jsx("button", { type: "button", className: authStyles.authModeLink, disabled: loginBusy, "data-testid": "auth-accept-invite-button", onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('invite'); }, children: "Accept Invite" })] })), (authMode !== 'login' && authMode !== 'register') && (_jsxs(_Fragment, { children: [authMode === 'verify' && (_jsx("button", { type: "button", className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive || !loginEmail.trim(), "data-testid": "auth-resend-verification-button", onClick: async () => {
|
|
1432
1439
|
setLoginBusy(true);
|
|
1433
1440
|
setLoginNotice(null);
|
|
1434
1441
|
setLoginError(null);
|
|
@@ -1444,7 +1451,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, initialActivityEn
|
|
|
1444
1451
|
setLoginError(formatAuthError(sent));
|
|
1445
1452
|
}
|
|
1446
1453
|
setLoginBusy(false);
|
|
1447
|
-
}, 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' }))] }))] })] })] }) }) }));
|
|
1454
|
+
}, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' })), _jsx("button", { type: "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", { type: "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", { type: "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' }))] }))] })] })] }) }) }));
|
|
1448
1455
|
}
|
|
1449
1456
|
if (shellRenderState === 'login-redirect') {
|
|
1450
1457
|
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..." })] }) }) }));
|
|
@@ -249,7 +249,7 @@ export class AnnotatedAttachmentSessionStore {
|
|
|
249
249
|
WHERE tenant_id = ?
|
|
250
250
|
AND workspace_id = ?
|
|
251
251
|
AND id = ?
|
|
252
|
-
`).run(normalizeId(input.taskId)
|
|
252
|
+
`).run(normalizeId(input.taskId), normalizeId(input.baseImageAssetId) || existing.baseImageAssetId, normalizeNullable(input.title), normalizeNullable(input.globalInstruction), JSON.stringify(Array.isArray(input.annotations) ? input.annotations : []), normalizeNullable(input.createdByActorId), normalizeNullable(input.updatedByActorId), normalizeId(input.createdAt) || existing.createdAt, normalizeId(input.updatedAt) || existing.updatedAt, normalizeNullable(input.deletedAt), this.tenantId, workspaceId, id);
|
|
253
253
|
return this.get(id, workspaceId, { includeDeleted: true });
|
|
254
254
|
}
|
|
255
255
|
update(input) {
|