@taskforcehq/taskforce 0.3.305 → 0.3.307
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/Taskforce.module.css +603 -107
- package/dist/TaskforceCore.js +216 -43
- package/dist/TaskforceCore.test.js +611 -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/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +561 -0
- package/dist/components/features/AgentsModule.d.ts +14 -1
- package/dist/components/features/AgentsModule.js +366 -18
- package/dist/components/features/AgentsModule.test.js +507 -8
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +7 -1
- package/dist/components/features/DocumentViewer.js +62 -4
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +51 -1
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +24 -29
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +61 -116
- 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 -21
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +78 -14
- package/dist/components/views/PlanComparisonPage.test.js +257 -0
- package/dist/components/views/PlansPage.js +127 -36
- package/dist/components/views/PlansPage.test.js +294 -12
- package/dist/components/views/StandaloneLayout.js +529 -592
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
- package/dist/components/views/panels/PlanningDrawer.js +270 -55
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +529 -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/config/envSchema.js +1 -0
- package/dist/core/AiProfileService.d.ts +46 -2
- package/dist/core/AiProfileService.js +1073 -82
- package/dist/core/AiProfileService.test.js +19 -1
- package/dist/core/AiProfiles.test.js +1249 -44
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +110 -23
- 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 +127 -6
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- 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 +418 -4
- 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/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +415 -40
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +1543 -266
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/Taskforce.mcpAuth.test.js +109 -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 +75 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- 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 +13 -4
- package/dist/hooks/sync/orchestratorShared.js +129 -48
- 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 +179 -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 +16 -3
- package/dist/hooks/sync/transfers.js +210 -66
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +928 -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/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
- package/dist/hooks/useSyncOrchestrator.js +409 -183
- 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 +145 -52
- package/dist/hooks/useTaskforce.js +592 -253
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
- package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.js +13 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
- 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/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +116 -10
- package/dist/mcp/runtime.d.ts +3 -0
- package/dist/mcp/runtime.js +1099 -185
- package/dist/mcp/runtime.test.js +1491 -140
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +192 -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/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
- 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 +124 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +111 -3
- package/dist/server/routes/admin.d.ts +3 -0
- package/dist/server/routes/admin.js +459 -28
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +26 -2
- package/dist/server/routes/auth.js +1170 -71
- package/dist/server/routes/authSupport.d.ts +5 -1
- package/dist/server/routes/authSupport.js +13 -2
- package/dist/server/routes/billing.js +372 -35
- package/dist/server/routes/billing.test.js +595 -12
- package/dist/server/routes/documents.d.ts +1 -0
- package/dist/server/routes/documents.js +182 -70
- package/dist/server/routes/shared.d.ts +28 -2
- package/dist/server/routes/shared.js +69 -14
- package/dist/server/routes/sync.integration.test.js +658 -39
- package/dist/server/routes/sync.js +74 -608
- 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 +182 -0
- package/dist/server/routes/tasks.js +55 -10
- package/dist/server/routes/workspaces.js +36 -5
- package/dist/server/routes.js +147 -11
- package/dist/server/routes.test.js +2704 -183
- 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/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- 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/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- 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 +19 -11
- package/dist/sync/collaborationSyncPayload.test.js +14 -1
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +9 -9
- package/dist/sync/contentSyncState.js +248 -107
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +11 -4
- package/dist/sync/syncApplyHandlers.js +115 -42
- package/dist/sync/syncApplyHandlers.test.js +251 -4
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +46 -0
- package/dist/sync/syncResourceAdapters.js +79 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +65 -1
- package/dist/sync/syncService.test.js +96 -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.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +132 -72
- package/dist/sync/workspacePullFeed.test.js +92 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +73 -6
- package/dist/sync/workspaceSyncModel.js +342 -73
- package/dist/sync/workspaceSyncModel.test.js +559 -14
- 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 +50 -2
- package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
- 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-D4rJKXzd.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
- package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.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-D5AcbO0L.js +1 -0
- package/dist/ui/assets/PlansPage-Dvqsz5zc.css +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/TaskContextUpload-uC5qx4Bv.js +1 -0
- package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
- package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
- package/dist/ui/assets/index-607WPo_X.js +4 -0
- package/dist/ui/assets/index-CYyodXsg.css +1 -0
- package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.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/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +8 -0
- package/dist/utils/assignees.js +10 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -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/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- 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 +9 -1
- package/dist/utils/taskActivity.js +290 -22
- package/dist/utils/taskActivity.test.js +141 -8
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- 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/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +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/TaskSettings-ln0aF7xc.js +0 -9
- 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/core/types.d.ts
CHANGED
|
@@ -275,6 +275,10 @@ export interface GlobalTaskforceSettings {
|
|
|
275
275
|
site?: {
|
|
276
276
|
showRunTaskforceLocally?: boolean;
|
|
277
277
|
pricingPageEnabled?: boolean;
|
|
278
|
+
animatedBackgroundEnabled?: boolean;
|
|
279
|
+
siteTheme?: 'dark' | 'light';
|
|
280
|
+
pricingPageTitle?: string;
|
|
281
|
+
pricingPageDescription?: string;
|
|
278
282
|
};
|
|
279
283
|
setup?: {
|
|
280
284
|
mode?: 'core' | 'operations';
|
|
@@ -287,6 +291,25 @@ export interface GlobalTaskforceSettings {
|
|
|
287
291
|
signedUploadTtlSeconds?: number;
|
|
288
292
|
signedDownloadTtlSeconds?: number;
|
|
289
293
|
};
|
|
294
|
+
oauthProviders?: {
|
|
295
|
+
google?: {
|
|
296
|
+
enabled?: boolean;
|
|
297
|
+
clientId?: string;
|
|
298
|
+
clientSecret?: string;
|
|
299
|
+
};
|
|
300
|
+
github?: {
|
|
301
|
+
enabled?: boolean;
|
|
302
|
+
clientId?: string;
|
|
303
|
+
clientSecret?: string;
|
|
304
|
+
};
|
|
305
|
+
apple?: {
|
|
306
|
+
enabled?: boolean;
|
|
307
|
+
servicesId?: string;
|
|
308
|
+
teamId?: string;
|
|
309
|
+
keyId?: string;
|
|
310
|
+
privateKeyPem?: string;
|
|
311
|
+
};
|
|
312
|
+
};
|
|
290
313
|
}
|
|
291
314
|
export interface SettingsSplitPayload {
|
|
292
315
|
system: GlobalTaskforceSettings;
|
|
@@ -303,11 +326,11 @@ export interface UserGlobalSyncSettings {
|
|
|
303
326
|
export type OnboardingPolicyMode = 'require_plan_selection' | 'auto_grant_free' | 'auto_start_trial';
|
|
304
327
|
export interface OnboardingPolicy {
|
|
305
328
|
mode: OnboardingPolicyMode;
|
|
306
|
-
|
|
329
|
+
planId: string | null;
|
|
307
330
|
}
|
|
308
331
|
export interface OnboardingPolicyValidationResult {
|
|
309
332
|
valid: boolean;
|
|
310
|
-
code?: '
|
|
333
|
+
code?: 'ONBOARDING_PLAN_REQUIRED' | 'ONBOARDING_PLAN_NOT_FOUND' | 'ONBOARDING_PLAN_NOT_ENABLED' | 'ONBOARDING_PLAN_MUST_BE_FREE' | 'ONBOARDING_PLAN_TRIAL_REQUIRED';
|
|
311
334
|
message?: string;
|
|
312
335
|
details?: Record<string, unknown>;
|
|
313
336
|
}
|
|
@@ -316,6 +339,36 @@ export type SystemRole = 'system_admin' | 'user';
|
|
|
316
339
|
export type PermissionMode = 'read-only' | 'read-write';
|
|
317
340
|
export type AuthTokenPurpose = 'email_verification' | 'password_reset' | 'invite_accept';
|
|
318
341
|
export type McpAccessTokenScope = 'tasks:read' | 'tasks:write' | 'workspace:read';
|
|
342
|
+
export type UserAuthProvider = 'password' | 'google' | 'github' | 'apple';
|
|
343
|
+
export interface UserAuthIdentity {
|
|
344
|
+
id: string;
|
|
345
|
+
tenantId: string;
|
|
346
|
+
userId: string;
|
|
347
|
+
provider: UserAuthProvider;
|
|
348
|
+
providerSubject: string | null;
|
|
349
|
+
providerEmail: string | null;
|
|
350
|
+
providerEmailVerified: boolean | null;
|
|
351
|
+
displayNameSnapshot: string | null;
|
|
352
|
+
avatarUrlSnapshot: string | null;
|
|
353
|
+
createdAt: string;
|
|
354
|
+
updatedAt: string;
|
|
355
|
+
lastLoginAt: string | null;
|
|
356
|
+
linkedAt: string | null;
|
|
357
|
+
disabledAt: string | null;
|
|
358
|
+
}
|
|
359
|
+
export type InviteeState = 'pending_setup' | 'existing_account';
|
|
360
|
+
export interface InviteAcceptanceDetails {
|
|
361
|
+
state: 'valid' | 'expired' | 'used' | 'missing' | 'revoked';
|
|
362
|
+
email?: string;
|
|
363
|
+
userId?: string;
|
|
364
|
+
workspaceId?: string;
|
|
365
|
+
inviteeState?: InviteeState;
|
|
366
|
+
availableMethods?: UserAuthProvider[];
|
|
367
|
+
/** @deprecated use inviteeState */
|
|
368
|
+
inviteeKind?: 'existing_user' | 'new_user';
|
|
369
|
+
/** @deprecated use availableMethods */
|
|
370
|
+
passwordRequired?: boolean;
|
|
371
|
+
}
|
|
319
372
|
export type McpAccessTokenStatus = 'active' | 'revoked' | 'expired';
|
|
320
373
|
export type McpOAuthProvider = 'chatgpt' | 'claude';
|
|
321
374
|
export type McpOAuthClientStatus = 'active' | 'revoked';
|
|
@@ -326,6 +379,8 @@ export interface UserAccessRecord {
|
|
|
326
379
|
role: AccessRole;
|
|
327
380
|
permissionMode: PermissionMode;
|
|
328
381
|
disabled: boolean;
|
|
382
|
+
accountDisabled?: boolean;
|
|
383
|
+
workspaceDisabled?: boolean;
|
|
329
384
|
betaAccess: boolean;
|
|
330
385
|
}
|
|
331
386
|
export interface UserIdentityRecord {
|
|
@@ -340,6 +395,7 @@ export interface WorkspaceUserRecord {
|
|
|
340
395
|
userId: string;
|
|
341
396
|
email: string;
|
|
342
397
|
displayName?: string | null;
|
|
398
|
+
avatarUrl?: string | null;
|
|
343
399
|
role: AccessRole;
|
|
344
400
|
permissionMode: PermissionMode;
|
|
345
401
|
betaAccess: boolean;
|
|
@@ -453,6 +509,9 @@ export interface PlanFeatureCatalogItem {
|
|
|
453
509
|
featureKey: string;
|
|
454
510
|
label: string;
|
|
455
511
|
description: string;
|
|
512
|
+
publicLabel?: string | null;
|
|
513
|
+
publicDescription?: string | null;
|
|
514
|
+
publicDisplayOrder?: number | null;
|
|
456
515
|
allowedAccessModes: PlanFeatureAccess[];
|
|
457
516
|
configTemplate: Record<string, unknown>;
|
|
458
517
|
dependsOn?: string[];
|
|
@@ -470,10 +529,20 @@ export interface PlanVersionSnapshot {
|
|
|
470
529
|
export interface PlanCatalogSnapshot {
|
|
471
530
|
planId: string;
|
|
472
531
|
displayName: string;
|
|
532
|
+
description: string | null;
|
|
473
533
|
status: 'active' | 'archived';
|
|
474
534
|
createdAt: string;
|
|
475
535
|
updatedAt: string;
|
|
476
536
|
}
|
|
537
|
+
export interface OnboardingPlanOption {
|
|
538
|
+
planId: string;
|
|
539
|
+
planDisplayName: string;
|
|
540
|
+
defaultPlanVersionId: string;
|
|
541
|
+
defaultVersionNumber: number;
|
|
542
|
+
planStatus: 'active' | 'archived';
|
|
543
|
+
supportsAutoGrantFree: boolean;
|
|
544
|
+
supportsAutoStartTrial: boolean;
|
|
545
|
+
}
|
|
477
546
|
export interface AccountEntitlementSnapshot {
|
|
478
547
|
accountId: string;
|
|
479
548
|
planVersionId: string;
|
|
@@ -520,6 +589,7 @@ export interface PasswordAuthResult {
|
|
|
520
589
|
userId: string;
|
|
521
590
|
workspaceId: string;
|
|
522
591
|
role: AccessRole;
|
|
592
|
+
identityId?: string;
|
|
523
593
|
};
|
|
524
594
|
code?: 'INVALID_CREDENTIALS' | 'EMAIL_NOT_VERIFIED';
|
|
525
595
|
}
|
|
@@ -612,4 +682,7 @@ export interface McpOAuthAccessTokenAuthResult {
|
|
|
612
682
|
provider: McpOAuthProvider;
|
|
613
683
|
scopes: McpAccessTokenScope[];
|
|
614
684
|
status: McpOAuthGrantStatus;
|
|
685
|
+
aiProfileId?: string | null;
|
|
686
|
+
aiProfileToken?: string | null;
|
|
687
|
+
aiProfileName?: string | null;
|
|
615
688
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { useCallback, useEffect } from 'react';
|
|
2
2
|
import { createDefaultAssigneeOptions } from '../../utils/assignees';
|
|
3
|
+
import { logBootstrapDebug } from '../workspace/workspaceLocalState';
|
|
3
4
|
import { persistLocalMutationActorUserId, readLocalMutationActorUserId } from '../../utils/taskforceApiClient';
|
|
5
|
+
import { AUTH_SESSION_REQUEST_TIMEOUT_MS } from '../bootstrapTimeouts';
|
|
6
|
+
function getBootstrapTimestamp() {
|
|
7
|
+
return typeof performance !== 'undefined' ? performance.now() : Date.now();
|
|
8
|
+
}
|
|
4
9
|
export function useTaskforceAuthBootstrap({ runtimeConfigReady, shouldProbeCloudAuth, authSessionResolved, resolveCloudAuthUrl, authOnlyCloudMode, authRequiredError, runtimeMode, workspaceSelectionScope, markBootstrapPhase, markBootstrapStalled, setRuntimeMode, setAuthRequiredForApi, setIsAuthenticated, setAuthUserId, setAuthWorkspaceId, setAuthUserEmail, setAuthUserDisplayName, setAuthUserAvatarUrl, setUserGlobalSyncStatus, setUserGlobalSyncError, setHasBetaAccess, setAvailableWorkspaces, setHydratedWorkspaceRole, setAssigneeOptions, setAuthBlocked, setAuthSessionResolved, setError, applyResolvedWorkspaceId, readPersistedWorkspaceId, authSessionRequestRef, authSessionEpochRef, authSessionLastCheckedAtRef, authSessionLastResultRef, isLoopbackHost, setAuthStateReadyRefs }) {
|
|
5
10
|
const checkAuthSession = useCallback(async (options) => {
|
|
6
11
|
const force = options?.force === true;
|
|
@@ -41,11 +46,20 @@ export function useTaskforceAuthBootstrap({ runtimeConfigReady, shouldProbeCloud
|
|
|
41
46
|
const requestEpoch = ++authSessionEpochRef.current;
|
|
42
47
|
let request = null;
|
|
43
48
|
request = (async () => {
|
|
49
|
+
const startedAt = getBootstrapTimestamp();
|
|
44
50
|
const abortController = new AbortController();
|
|
45
51
|
const timeoutId = typeof window !== 'undefined'
|
|
46
|
-
? window.setTimeout(() => abortController.abort(),
|
|
52
|
+
? window.setTimeout(() => abortController.abort(), AUTH_SESSION_REQUEST_TIMEOUT_MS)
|
|
47
53
|
: null;
|
|
48
54
|
const isStaleRequest = () => authSessionEpochRef.current !== requestEpoch;
|
|
55
|
+
const logResult = (event, details) => {
|
|
56
|
+
logBootstrapDebug(event, {
|
|
57
|
+
durationMs: Math.max(0, Math.round(getBootstrapTimestamp() - startedAt)),
|
|
58
|
+
force,
|
|
59
|
+
sessionUrl,
|
|
60
|
+
...details
|
|
61
|
+
});
|
|
62
|
+
};
|
|
49
63
|
try {
|
|
50
64
|
const res = await fetch(sessionUrl, {
|
|
51
65
|
method: 'GET',
|
|
@@ -59,6 +73,7 @@ export function useTaskforceAuthBootstrap({ runtimeConfigReady, shouldProbeCloud
|
|
|
59
73
|
if (res.status === 429) {
|
|
60
74
|
setAuthSessionResolved(true);
|
|
61
75
|
setAuthStateReadyRefs(authSessionLastResultRef.current, true, false);
|
|
76
|
+
logResult('auth_session_rate_limited', { status: res.status });
|
|
62
77
|
return authSessionLastResultRef.current;
|
|
63
78
|
}
|
|
64
79
|
if (!res.ok) {
|
|
@@ -70,6 +85,7 @@ export function useTaskforceAuthBootstrap({ runtimeConfigReady, shouldProbeCloud
|
|
|
70
85
|
setAuthSessionResolved(true);
|
|
71
86
|
setAuthStateReadyRefs(false, true, false);
|
|
72
87
|
authSessionLastResultRef.current = false;
|
|
88
|
+
logResult('auth_session_request_failed', { status: res.status });
|
|
73
89
|
return false;
|
|
74
90
|
}
|
|
75
91
|
const data = await res.json();
|
|
@@ -117,9 +133,16 @@ export function useTaskforceAuthBootstrap({ runtimeConfigReady, shouldProbeCloud
|
|
|
117
133
|
authSessionLastResultRef.current = authenticated;
|
|
118
134
|
if (authenticated)
|
|
119
135
|
markBootstrapPhase('ready');
|
|
136
|
+
logResult('auth_session_resolved', {
|
|
137
|
+
status: res.status,
|
|
138
|
+
authenticated,
|
|
139
|
+
workspaceId: authenticated ? workspaceId : '',
|
|
140
|
+
userId: authenticated ? userId : 'anonymous',
|
|
141
|
+
authRequiredForApi: nextAuthRequiredForApi
|
|
142
|
+
});
|
|
120
143
|
return authenticated;
|
|
121
144
|
}
|
|
122
|
-
catch {
|
|
145
|
+
catch (error) {
|
|
123
146
|
if (isStaleRequest()) {
|
|
124
147
|
return authSessionLastResultRef.current;
|
|
125
148
|
}
|
|
@@ -129,6 +152,9 @@ export function useTaskforceAuthBootstrap({ runtimeConfigReady, shouldProbeCloud
|
|
|
129
152
|
setAuthStateReadyRefs(false, true, false);
|
|
130
153
|
authSessionLastResultRef.current = false;
|
|
131
154
|
markBootstrapStalled('Unable to verify your session.');
|
|
155
|
+
logResult('auth_session_exception', {
|
|
156
|
+
error: error instanceof Error ? error.message : String(error)
|
|
157
|
+
});
|
|
132
158
|
return authSessionLastResultRef.current;
|
|
133
159
|
}
|
|
134
160
|
finally {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const BOOTSTRAP_REQUEST_TIMEOUT_MS = 12000;
|
|
2
|
+
export declare const CLOUD_BOOTSTRAP_REQUEST_TIMEOUT_MS = 30000;
|
|
3
|
+
export declare const AUTH_SESSION_REQUEST_TIMEOUT_MS = 20000;
|
|
4
|
+
export declare function resolveBootstrapRequestTimeoutMs(runtimeMode: 'local' | 'cloud'): number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const BOOTSTRAP_REQUEST_TIMEOUT_MS = 12_000;
|
|
2
|
+
export const CLOUD_BOOTSTRAP_REQUEST_TIMEOUT_MS = 30_000;
|
|
3
|
+
export const AUTH_SESSION_REQUEST_TIMEOUT_MS = 20_000;
|
|
4
|
+
export function resolveBootstrapRequestTimeoutMs(runtimeMode) {
|
|
5
|
+
return runtimeMode === 'cloud'
|
|
6
|
+
? CLOUD_BOOTSTRAP_REQUEST_TIMEOUT_MS
|
|
7
|
+
: BOOTSTRAP_REQUEST_TIMEOUT_MS;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { AUTH_SESSION_REQUEST_TIMEOUT_MS, BOOTSTRAP_REQUEST_TIMEOUT_MS, CLOUD_BOOTSTRAP_REQUEST_TIMEOUT_MS, resolveBootstrapRequestTimeoutMs } from './bootstrapTimeouts';
|
|
3
|
+
describe('bootstrap timeout budgets', () => {
|
|
4
|
+
it('keeps local bootstrap checks short', () => {
|
|
5
|
+
expect(resolveBootstrapRequestTimeoutMs('local')).toBe(BOOTSTRAP_REQUEST_TIMEOUT_MS);
|
|
6
|
+
});
|
|
7
|
+
it('gives cloud bootstrap checks enough room for edge delays', () => {
|
|
8
|
+
expect(resolveBootstrapRequestTimeoutMs('cloud')).toBe(CLOUD_BOOTSTRAP_REQUEST_TIMEOUT_MS);
|
|
9
|
+
expect(CLOUD_BOOTSTRAP_REQUEST_TIMEOUT_MS).toBeGreaterThan(BOOTSTRAP_REQUEST_TIMEOUT_MS);
|
|
10
|
+
expect(AUTH_SESSION_REQUEST_TIMEOUT_MS).toBeGreaterThan(BOOTSTRAP_REQUEST_TIMEOUT_MS);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -45,6 +45,8 @@ export function resolveRepairPhase(args) {
|
|
|
45
45
|
return 'provision-local';
|
|
46
46
|
if (workspaceSyncPhase === 'attach-cloud')
|
|
47
47
|
return 'attach-cloud';
|
|
48
|
+
if (workspaceSyncPhase === 'active' || lastBootstrapPhase === 'active')
|
|
49
|
+
return 'active';
|
|
48
50
|
if (lastBootstrapPhase === 'provision-local' || lastBootstrapPhase === 'attach-cloud') {
|
|
49
51
|
return lastBootstrapPhase;
|
|
50
52
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { WorkspaceSyncPhase } from '../../sync/workspaceSyncState';
|
|
2
|
+
export type WorkspaceSyncBlockedReason = 'cloud-auth-unconfigured' | 'runtime-not-local' | 'sync-disabled' | 'invalid-workspace' | 'repair-active' | 'attach-cloud' | 'provision-local' | 'auth-required' | 'push-in-flight' | 'pull-in-flight' | 'retry-pending' | 'lease-held';
|
|
3
|
+
export type WorkspaceSyncOperation = 'pull' | 'push' | 'repair';
|
|
4
|
+
export type WorkspaceSyncControlPlaneDecision = {
|
|
5
|
+
allowed: true;
|
|
6
|
+
} | {
|
|
7
|
+
allowed: false;
|
|
8
|
+
reason: WorkspaceSyncBlockedReason;
|
|
9
|
+
retainPendingSignature: boolean;
|
|
10
|
+
};
|
|
11
|
+
interface WorkspaceSyncControlPlaneBaseArgs {
|
|
12
|
+
cloudAuthConfigured: boolean;
|
|
13
|
+
runtimeMode: 'local' | 'cloud';
|
|
14
|
+
workspaceCloudSyncEnabled: boolean;
|
|
15
|
+
currentWorkspaceId: string;
|
|
16
|
+
isAuthenticated: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface PushSyncReadinessArgs extends WorkspaceSyncControlPlaneBaseArgs {
|
|
19
|
+
workspaceSyncPhase: WorkspaceSyncPhase;
|
|
20
|
+
repairModeActive: boolean;
|
|
21
|
+
repairModeBypass: boolean;
|
|
22
|
+
pushInFlight: boolean;
|
|
23
|
+
pullInFlight: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface PullSyncReadinessArgs extends WorkspaceSyncControlPlaneBaseArgs {
|
|
26
|
+
workspaceSyncPhase: WorkspaceSyncPhase;
|
|
27
|
+
repairModeActive: boolean;
|
|
28
|
+
repairModeBypass: boolean;
|
|
29
|
+
retryPending: boolean;
|
|
30
|
+
pushInFlight: boolean;
|
|
31
|
+
pullInFlight: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function resolvePushSyncReadiness(args: PushSyncReadinessArgs): WorkspaceSyncControlPlaneDecision;
|
|
34
|
+
export declare function resolvePullSyncReadiness(args: PullSyncReadinessArgs): WorkspaceSyncControlPlaneDecision;
|
|
35
|
+
export declare function resolveRetrySyncReadiness(args: WorkspaceSyncControlPlaneBaseArgs): WorkspaceSyncControlPlaneDecision;
|
|
36
|
+
export declare function createWorkspaceSyncLeaseHeldDecision(operation: WorkspaceSyncOperation): WorkspaceSyncControlPlaneDecision;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { isValidWorkspaceKey } from './orchestratorShared';
|
|
2
|
+
const ALLOW_SYNC_OPERATION = { allowed: true };
|
|
3
|
+
function blockSyncOperation(reason, options) {
|
|
4
|
+
return {
|
|
5
|
+
allowed: false,
|
|
6
|
+
reason,
|
|
7
|
+
retainPendingSignature: options?.retainPendingSignature === true
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function resolveBaseSyncReadiness(args, options) {
|
|
11
|
+
if (!args.cloudAuthConfigured)
|
|
12
|
+
return blockSyncOperation('cloud-auth-unconfigured');
|
|
13
|
+
if (args.runtimeMode !== 'local')
|
|
14
|
+
return blockSyncOperation('runtime-not-local');
|
|
15
|
+
if (!args.workspaceCloudSyncEnabled)
|
|
16
|
+
return blockSyncOperation('sync-disabled');
|
|
17
|
+
if ((options?.requireValidWorkspace ?? true) && !isValidWorkspaceKey(args.currentWorkspaceId)) {
|
|
18
|
+
return blockSyncOperation('invalid-workspace');
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export function resolvePushSyncReadiness(args) {
|
|
23
|
+
const baseReadiness = resolveBaseSyncReadiness(args);
|
|
24
|
+
if (baseReadiness)
|
|
25
|
+
return baseReadiness;
|
|
26
|
+
if (args.repairModeActive && !args.repairModeBypass) {
|
|
27
|
+
return blockSyncOperation('repair-active', { retainPendingSignature: true });
|
|
28
|
+
}
|
|
29
|
+
if (args.workspaceSyncPhase === 'attach-cloud') {
|
|
30
|
+
return blockSyncOperation('attach-cloud', { retainPendingSignature: true });
|
|
31
|
+
}
|
|
32
|
+
if (!args.isAuthenticated) {
|
|
33
|
+
return blockSyncOperation('auth-required');
|
|
34
|
+
}
|
|
35
|
+
if (args.pushInFlight) {
|
|
36
|
+
return blockSyncOperation('push-in-flight', { retainPendingSignature: true });
|
|
37
|
+
}
|
|
38
|
+
if (args.pullInFlight) {
|
|
39
|
+
return blockSyncOperation('pull-in-flight', { retainPendingSignature: true });
|
|
40
|
+
}
|
|
41
|
+
return ALLOW_SYNC_OPERATION;
|
|
42
|
+
}
|
|
43
|
+
export function resolvePullSyncReadiness(args) {
|
|
44
|
+
const baseReadiness = resolveBaseSyncReadiness(args);
|
|
45
|
+
if (baseReadiness)
|
|
46
|
+
return baseReadiness;
|
|
47
|
+
if (args.repairModeActive && !args.repairModeBypass) {
|
|
48
|
+
return blockSyncOperation('repair-active');
|
|
49
|
+
}
|
|
50
|
+
if (args.workspaceSyncPhase === 'provision-local') {
|
|
51
|
+
return blockSyncOperation('provision-local');
|
|
52
|
+
}
|
|
53
|
+
if (args.retryPending) {
|
|
54
|
+
return blockSyncOperation('retry-pending');
|
|
55
|
+
}
|
|
56
|
+
if (!args.isAuthenticated) {
|
|
57
|
+
return blockSyncOperation('auth-required');
|
|
58
|
+
}
|
|
59
|
+
if (args.pullInFlight) {
|
|
60
|
+
return blockSyncOperation('pull-in-flight');
|
|
61
|
+
}
|
|
62
|
+
if (args.pushInFlight) {
|
|
63
|
+
return blockSyncOperation('push-in-flight');
|
|
64
|
+
}
|
|
65
|
+
return ALLOW_SYNC_OPERATION;
|
|
66
|
+
}
|
|
67
|
+
export function resolveRetrySyncReadiness(args) {
|
|
68
|
+
const baseReadiness = resolveBaseSyncReadiness(args, { requireValidWorkspace: false });
|
|
69
|
+
if (baseReadiness)
|
|
70
|
+
return baseReadiness;
|
|
71
|
+
if (!args.isAuthenticated) {
|
|
72
|
+
return blockSyncOperation('auth-required');
|
|
73
|
+
}
|
|
74
|
+
return ALLOW_SYNC_OPERATION;
|
|
75
|
+
}
|
|
76
|
+
export function createWorkspaceSyncLeaseHeldDecision(operation) {
|
|
77
|
+
return blockSyncOperation('lease-held', { retainPendingSignature: operation === 'push' });
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createWorkspaceSyncLeaseHeldDecision, resolvePullSyncReadiness, resolvePushSyncReadiness, resolveRetrySyncReadiness, } from './controlPlane';
|
|
3
|
+
const makeBaseArgs = () => ({
|
|
4
|
+
cloudAuthConfigured: true,
|
|
5
|
+
runtimeMode: 'local',
|
|
6
|
+
workspaceCloudSyncEnabled: true,
|
|
7
|
+
currentWorkspaceId: 'workspace-123',
|
|
8
|
+
isAuthenticated: true
|
|
9
|
+
});
|
|
10
|
+
describe('sync control plane', () => {
|
|
11
|
+
it('blocks push during repair and retains the pending signature', () => {
|
|
12
|
+
expect(resolvePushSyncReadiness({
|
|
13
|
+
...makeBaseArgs(),
|
|
14
|
+
workspaceSyncPhase: 'active',
|
|
15
|
+
repairModeActive: true,
|
|
16
|
+
repairModeBypass: false,
|
|
17
|
+
pushInFlight: false,
|
|
18
|
+
pullInFlight: false
|
|
19
|
+
})).toEqual({
|
|
20
|
+
allowed: false,
|
|
21
|
+
reason: 'repair-active',
|
|
22
|
+
retainPendingSignature: true
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it('allows repair push to bypass the repair-active gate', () => {
|
|
26
|
+
expect(resolvePushSyncReadiness({
|
|
27
|
+
...makeBaseArgs(),
|
|
28
|
+
workspaceSyncPhase: 'active',
|
|
29
|
+
repairModeActive: true,
|
|
30
|
+
repairModeBypass: true,
|
|
31
|
+
pushInFlight: false,
|
|
32
|
+
pullInFlight: false
|
|
33
|
+
})).toEqual({ allowed: true });
|
|
34
|
+
});
|
|
35
|
+
it('blocks push during attach-cloud and retains the pending signature', () => {
|
|
36
|
+
expect(resolvePushSyncReadiness({
|
|
37
|
+
...makeBaseArgs(),
|
|
38
|
+
workspaceSyncPhase: 'attach-cloud',
|
|
39
|
+
repairModeActive: false,
|
|
40
|
+
repairModeBypass: false,
|
|
41
|
+
pushInFlight: false,
|
|
42
|
+
pullInFlight: false
|
|
43
|
+
})).toEqual({
|
|
44
|
+
allowed: false,
|
|
45
|
+
reason: 'attach-cloud',
|
|
46
|
+
retainPendingSignature: true
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
it('blocks pull during provision-local', () => {
|
|
50
|
+
expect(resolvePullSyncReadiness({
|
|
51
|
+
...makeBaseArgs(),
|
|
52
|
+
workspaceSyncPhase: 'provision-local',
|
|
53
|
+
repairModeActive: false,
|
|
54
|
+
repairModeBypass: false,
|
|
55
|
+
retryPending: false,
|
|
56
|
+
pushInFlight: false,
|
|
57
|
+
pullInFlight: false
|
|
58
|
+
})).toEqual({
|
|
59
|
+
allowed: false,
|
|
60
|
+
reason: 'provision-local',
|
|
61
|
+
retainPendingSignature: false
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
it('blocks pull when a retry is already pending', () => {
|
|
65
|
+
expect(resolvePullSyncReadiness({
|
|
66
|
+
...makeBaseArgs(),
|
|
67
|
+
workspaceSyncPhase: 'active',
|
|
68
|
+
repairModeActive: false,
|
|
69
|
+
repairModeBypass: false,
|
|
70
|
+
retryPending: true,
|
|
71
|
+
pushInFlight: false,
|
|
72
|
+
pullInFlight: false
|
|
73
|
+
})).toEqual({
|
|
74
|
+
allowed: false,
|
|
75
|
+
reason: 'retry-pending',
|
|
76
|
+
retainPendingSignature: false
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
it('surfaces auth-required for retry readiness before the session is refreshed', () => {
|
|
80
|
+
expect(resolveRetrySyncReadiness({
|
|
81
|
+
...makeBaseArgs(),
|
|
82
|
+
isAuthenticated: false
|
|
83
|
+
})).toEqual({
|
|
84
|
+
allowed: false,
|
|
85
|
+
reason: 'auth-required',
|
|
86
|
+
retainPendingSignature: false
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
it('rejects invalid workspace ids for transfer operations', () => {
|
|
90
|
+
expect(resolvePushSyncReadiness({
|
|
91
|
+
...makeBaseArgs(),
|
|
92
|
+
currentWorkspaceId: 'default',
|
|
93
|
+
workspaceSyncPhase: 'active',
|
|
94
|
+
repairModeActive: false,
|
|
95
|
+
repairModeBypass: false,
|
|
96
|
+
pushInFlight: false,
|
|
97
|
+
pullInFlight: false
|
|
98
|
+
})).toEqual({
|
|
99
|
+
allowed: false,
|
|
100
|
+
reason: 'invalid-workspace',
|
|
101
|
+
retainPendingSignature: false
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
it('marks lease contention as retaining the pending signature only for push', () => {
|
|
105
|
+
expect(createWorkspaceSyncLeaseHeldDecision('push')).toEqual({
|
|
106
|
+
allowed: false,
|
|
107
|
+
reason: 'lease-held',
|
|
108
|
+
retainPendingSignature: true
|
|
109
|
+
});
|
|
110
|
+
expect(createWorkspaceSyncLeaseHeldDecision('pull')).toEqual({
|
|
111
|
+
allowed: false,
|
|
112
|
+
reason: 'lease-held',
|
|
113
|
+
retainPendingSignature: false
|
|
114
|
+
});
|
|
115
|
+
expect(createWorkspaceSyncLeaseHeldDecision('repair')).toEqual({
|
|
116
|
+
allowed: false,
|
|
117
|
+
reason: 'lease-held',
|
|
118
|
+
retainPendingSignature: false
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { WorkspaceSyncPhase } from '../../sync/workspaceSyncState';
|
|
2
|
+
export type WorkspaceSyncPresentationStatus = 'off' | 'syncing' | 'attention' | 'healthy';
|
|
3
|
+
interface WorkspaceSyncPresentationArgs {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
phase: WorkspaceSyncPhase;
|
|
6
|
+
busy: boolean;
|
|
7
|
+
retryAt: string | null;
|
|
8
|
+
lastErrorMessage: string | null;
|
|
9
|
+
}
|
|
10
|
+
interface WorkspaceSyncLifecycleBaseArgs {
|
|
11
|
+
cloudAuthConfigured: boolean;
|
|
12
|
+
runtimeMode: 'local' | 'cloud';
|
|
13
|
+
workspaceCloudSyncEnabled: boolean;
|
|
14
|
+
authSessionResolved: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface WorkspaceSyncAutomaticPullArgs extends WorkspaceSyncLifecycleBaseArgs {
|
|
17
|
+
workspaceSyncPhase: WorkspaceSyncPhase;
|
|
18
|
+
lastPullAt: string | null;
|
|
19
|
+
retryPending: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface WorkspaceSyncFullReconcileArgs extends WorkspaceSyncLifecycleBaseArgs {
|
|
22
|
+
workspaceSyncPhase: WorkspaceSyncPhase;
|
|
23
|
+
isAuthenticated: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface WorkspaceSyncStartupRepairArgs extends WorkspaceSyncFullReconcileArgs {
|
|
26
|
+
alreadyRan: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface WorkspaceSyncReactivePushArgs extends WorkspaceSyncLifecycleBaseArgs {
|
|
29
|
+
workspaceSyncPhase: WorkspaceSyncPhase;
|
|
30
|
+
workspaceSyncReferenceSnapshotsReady: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function resolveWorkspaceSyncPresentation({ enabled, phase, busy, retryAt, lastErrorMessage }: WorkspaceSyncPresentationArgs): {
|
|
33
|
+
status: WorkspaceSyncPresentationStatus;
|
|
34
|
+
summary: string;
|
|
35
|
+
recommendedAction: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function shouldScheduleWorkspaceReactivePush(args: WorkspaceSyncReactivePushArgs): boolean;
|
|
38
|
+
export declare function shouldStartWorkspacePushWatchdog(args: WorkspaceSyncReactivePushArgs): boolean;
|
|
39
|
+
export declare function resolveWorkspaceAutomaticPullPolicy(args: WorkspaceSyncAutomaticPullArgs): {
|
|
40
|
+
shouldStart: boolean;
|
|
41
|
+
shouldKickOffImmediately: boolean;
|
|
42
|
+
};
|
|
43
|
+
export declare function shouldStartWorkspacePeriodicFullReconcile(args: WorkspaceSyncFullReconcileArgs): boolean;
|
|
44
|
+
export declare function shouldRunWorkspaceStartupRepair(args: WorkspaceSyncStartupRepairArgs): boolean;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
function canRunLocalWorkspaceSyncLifecycle(args) {
|
|
2
|
+
return args.cloudAuthConfigured
|
|
3
|
+
&& args.runtimeMode === 'local'
|
|
4
|
+
&& args.workspaceCloudSyncEnabled
|
|
5
|
+
&& args.authSessionResolved;
|
|
6
|
+
}
|
|
7
|
+
export function resolveWorkspaceSyncPresentation({ enabled, phase, busy, retryAt, lastErrorMessage }) {
|
|
8
|
+
if (!enabled) {
|
|
9
|
+
return {
|
|
10
|
+
status: 'off',
|
|
11
|
+
summary: 'Sync is turned off for this workspace.',
|
|
12
|
+
recommendedAction: 'Turn on sync when you are ready to back up this workspace.'
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (phase === 'provision-local') {
|
|
16
|
+
return {
|
|
17
|
+
status: 'syncing',
|
|
18
|
+
summary: busy
|
|
19
|
+
? 'Uploading this workspace to cloud for the first time.'
|
|
20
|
+
: 'Preparing the first upload to cloud.',
|
|
21
|
+
recommendedAction: 'Keep this window open while the first upload finishes. If it seems stalled, press Sync.'
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (phase === 'attach-cloud') {
|
|
25
|
+
return {
|
|
26
|
+
status: 'syncing',
|
|
27
|
+
summary: busy
|
|
28
|
+
? 'Pulling the cloud workspace into this device.'
|
|
29
|
+
: 'Waiting for the first cloud pull into this device.',
|
|
30
|
+
recommendedAction: 'Keep this window open for the first cloud pull. If it does not move, press Repair.'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (retryAt) {
|
|
34
|
+
return {
|
|
35
|
+
status: 'attention',
|
|
36
|
+
summary: 'Sync hit a temporary problem and will retry automatically.',
|
|
37
|
+
recommendedAction: 'Wait for the automatic retry, or press Sync to retry now.'
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (lastErrorMessage || phase === 'error') {
|
|
41
|
+
return {
|
|
42
|
+
status: 'attention',
|
|
43
|
+
summary: 'Sync needs attention before it can continue.',
|
|
44
|
+
recommendedAction: 'Press Sync to retry. If the same error keeps returning, press Repair.'
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (busy) {
|
|
48
|
+
return {
|
|
49
|
+
status: 'syncing',
|
|
50
|
+
summary: 'Sync is currently running.',
|
|
51
|
+
recommendedAction: 'No action needed.'
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
status: 'healthy',
|
|
56
|
+
summary: 'Sync is healthy.',
|
|
57
|
+
recommendedAction: 'No action needed.'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function shouldScheduleWorkspaceReactivePush(args) {
|
|
61
|
+
return canRunLocalWorkspaceSyncLifecycle(args)
|
|
62
|
+
&& args.workspaceSyncPhase !== 'attach-cloud'
|
|
63
|
+
&& args.workspaceSyncReferenceSnapshotsReady;
|
|
64
|
+
}
|
|
65
|
+
export function shouldStartWorkspacePushWatchdog(args) {
|
|
66
|
+
return canRunLocalWorkspaceSyncLifecycle(args)
|
|
67
|
+
&& args.workspaceSyncPhase === 'active'
|
|
68
|
+
&& args.workspaceSyncReferenceSnapshotsReady;
|
|
69
|
+
}
|
|
70
|
+
export function resolveWorkspaceAutomaticPullPolicy(args) {
|
|
71
|
+
if (!canRunLocalWorkspaceSyncLifecycle(args)) {
|
|
72
|
+
return { shouldStart: false, shouldKickOffImmediately: false };
|
|
73
|
+
}
|
|
74
|
+
if (args.workspaceSyncPhase === 'provision-local' || args.workspaceSyncPhase === 'error' || args.retryPending) {
|
|
75
|
+
return { shouldStart: false, shouldKickOffImmediately: false };
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
shouldStart: true,
|
|
79
|
+
shouldKickOffImmediately: args.workspaceSyncPhase === 'attach-cloud' || !args.lastPullAt
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function shouldStartWorkspacePeriodicFullReconcile(args) {
|
|
83
|
+
return canRunLocalWorkspaceSyncLifecycle(args)
|
|
84
|
+
&& args.isAuthenticated
|
|
85
|
+
&& args.workspaceSyncPhase === 'active';
|
|
86
|
+
}
|
|
87
|
+
export function shouldRunWorkspaceStartupRepair(args) {
|
|
88
|
+
return canRunLocalWorkspaceSyncLifecycle(args)
|
|
89
|
+
&& args.isAuthenticated
|
|
90
|
+
&& args.workspaceSyncPhase !== 'provision-local'
|
|
91
|
+
&& args.workspaceSyncPhase !== 'attach-cloud'
|
|
92
|
+
&& !args.alreadyRan;
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|