@taskforcehq/taskforce 0.3.301 → 0.3.303
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 +37 -2
- package/dist/TaskforceCore.filter-persistence.test.js +1 -1
- package/dist/TaskforceCore.js +72 -33
- package/dist/TaskforceCore.test.js +848 -130
- package/dist/components/features/TaskSettings.js +14 -82
- package/dist/components/features/TaskSettings.test.js +33 -70
- package/dist/components/features/settings/TaxonomyLibraryManager.js +8 -2
- package/dist/components/features/settings/TaxonomyLibraryManager.test.js +1 -1
- package/dist/components/task/TaskActionHeader.js +6 -3
- package/dist/components/task/TaskCard.js +6 -3
- package/dist/components/task/TaskForm.js +2 -2
- package/dist/components/task/TaskForm.test.js +41 -2
- package/dist/components/task/TaskKanban.test.js +17 -0
- package/dist/components/ui/ReferenceBadgeButton.js +1 -1
- package/dist/components/views/PlansPage.d.ts +3 -1
- package/dist/components/views/PlansPage.js +109 -49
- package/dist/components/views/PlansPage.test.d.ts +1 -0
- package/dist/components/views/PlansPage.test.js +100 -0
- package/dist/components/views/StandaloneLayout.d.ts +1 -0
- package/dist/components/views/StandaloneLayout.js +473 -256
- package/dist/components/views/panels/PlanningDrawer.js +18 -1
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +48 -0
- package/dist/components/views/standalone/modals/AccountHubModal.js +36 -0
- package/dist/components/views/standalone/modals/AccountHubModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +26 -0
- package/dist/components/views/standalone/modals/CreateWorkspaceConfirmModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/CreateWorkspaceConfirmModal.js +8 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +26 -0
- package/dist/components/views/standalone/modals/EditProfileModal.js +10 -0
- package/dist/components/views/standalone/modals/HelpModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/HelpModal.js +8 -0
- package/dist/components/views/standalone/modals/ScheduleWarningModal.d.ts +13 -0
- package/dist/components/views/standalone/modals/ScheduleWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +61 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.js +38 -0
- package/dist/components/views/standalone/modals/TeamManagementModal.d.ts +64 -0
- package/dist/components/views/standalone/modals/TeamManagementModal.js +10 -0
- package/dist/components/views/standalone/modals/types.d.ts +2 -0
- package/dist/components/views/standalone/modals/types.js +1 -0
- package/dist/components/views/teamManagementAccess.d.ts +1 -1
- package/dist/components/views/teamManagementAccess.js +2 -2
- package/dist/components/views/teamManagementAccess.test.js +3 -3
- package/dist/config/deployment.js +2 -2
- package/dist/config/deployment.test.js +5 -3
- package/dist/core/AiProfileService.js +7 -2
- package/dist/core/AiProfiles.test.js +19 -0
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +78 -18
- package/dist/core/PlanEntitlementService.d.ts +29 -5
- package/dist/core/PlanEntitlementService.js +297 -219
- package/dist/core/SignupMonetizationSettings.test.js +173 -49
- package/dist/core/SyncReconciliationService.d.ts +2 -0
- package/dist/core/SyncReconciliationService.js +3 -0
- package/dist/core/SystemAdmin.test.js +186 -96
- package/dist/core/TaskAuditTimeline.test.js +40 -0
- package/dist/core/Taskforce.d.ts +100 -10
- package/dist/core/Taskforce.ids.test.js +133 -0
- package/dist/core/Taskforce.js +459 -127
- package/dist/core/Taskforce.mcpAuth.test.js +0 -2
- package/dist/core/UserProfileAvatarDrafts.test.d.ts +1 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +111 -0
- package/dist/core/taskReferencePolicy.d.ts +28 -0
- package/dist/core/taskReferencePolicy.js +189 -0
- package/dist/core/types.d.ts +13 -12
- package/dist/hooks/tasks/useTaskFormActions.js +3 -0
- package/dist/hooks/useSyncOrchestrator.js +17 -3
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +97 -5
- package/dist/hooks/useTaskData.js +3 -2
- package/dist/hooks/useTaskData.test.js +66 -0
- package/dist/hooks/useTaskforce.d.ts +8 -0
- package/dist/hooks/useTaskforce.js +72 -19
- package/dist/hooks/useTaskforce.sync-behavior.test.js +185 -6
- package/dist/mcp/aiProfileBootstrap.d.ts +29 -0
- package/dist/mcp/aiProfileBootstrap.js +80 -0
- package/dist/mcp/aiProfileBootstrap.test.d.ts +1 -0
- package/dist/mcp/aiProfileBootstrap.test.js +68 -0
- package/dist/mcp/clientIntegrations.d.ts +2 -8
- package/dist/mcp/clientIntegrations.js +21 -40
- package/dist/mcp/clientIntegrations.test.js +28 -2
- package/dist/mcp/clientProfileDefaults.d.ts +12 -0
- package/dist/mcp/clientProfileDefaults.js +37 -0
- package/dist/mcp/runtime.d.ts +10 -7
- package/dist/mcp/runtime.js +131 -48
- package/dist/mcp/runtime.test.js +321 -83
- package/dist/migrations/billingSchemaParity.test.js +3 -0
- package/dist/migrations/taskSchemaMigrations.js +68 -1
- package/dist/qaOpen.test.d.ts +1 -0
- package/dist/qaOpen.test.js +56 -0
- package/dist/server/index.cookieProxy.test.js +2 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +17 -1
- package/dist/server/index.test.js +15 -1
- package/dist/server/mockStripe.d.ts +1 -0
- package/dist/server/mockStripe.js +2 -0
- package/dist/server/routes/admin.js +105 -45
- package/dist/server/routes/auth.d.ts +6 -0
- package/dist/server/routes/auth.js +505 -30
- package/dist/server/routes/billing.js +517 -24
- package/dist/server/routes/billing.test.js +967 -45
- package/dist/server/routes/documents.js +6 -1
- package/dist/server/routes/shared.d.ts +1 -1
- package/dist/server/routes/shared.js +16 -6
- package/dist/server/routes/sync.integration.test.js +290 -0
- package/dist/server/routes/sync.js +234 -1922
- package/dist/server/routes/tasks.js +18 -4
- package/dist/server/routes.js +29 -22
- package/dist/server/routes.test.js +639 -82
- package/dist/shared/runtimeContract.d.ts +1 -1
- package/dist/sync/cloudSyncApi.d.ts +1 -0
- package/dist/sync/collaborationSyncPayload.d.ts +17 -0
- package/dist/sync/collaborationSyncPayload.js +131 -0
- package/dist/sync/collaborationSyncPayload.test.d.ts +1 -0
- package/dist/sync/collaborationSyncPayload.test.js +104 -0
- package/dist/sync/collaborationSyncState.d.ts +15 -0
- package/dist/sync/collaborationSyncState.js +60 -0
- package/dist/sync/contentSyncPayload.d.ts +45 -0
- package/dist/sync/contentSyncPayload.js +104 -0
- package/dist/sync/contentSyncPayload.test.d.ts +1 -0
- package/dist/sync/contentSyncPayload.test.js +104 -0
- package/dist/sync/contentSyncState.d.ts +98 -0
- package/dist/sync/contentSyncState.js +1004 -0
- package/dist/sync/planningSyncPayload.d.ts +9 -0
- package/dist/sync/planningSyncPayload.js +82 -0
- package/dist/sync/planningSyncPayload.test.d.ts +1 -0
- package/dist/sync/planningSyncPayload.test.js +68 -0
- package/dist/sync/syncApplyHandlers.d.ts +83 -0
- package/dist/sync/syncApplyHandlers.js +445 -0
- package/dist/sync/syncService.d.ts +1 -0
- package/dist/sync/syncService.js +21 -8
- package/dist/sync/taskSyncPayload.d.ts +33 -0
- package/dist/sync/taskSyncPayload.js +126 -0
- package/dist/sync/taskSyncPayload.test.d.ts +1 -0
- package/dist/sync/taskSyncPayload.test.js +54 -0
- package/dist/sync/workspacePullFeed.d.ts +38 -0
- package/dist/sync/workspacePullFeed.js +349 -0
- package/dist/sync/workspacePullFeed.test.d.ts +1 -0
- package/dist/sync/workspacePullFeed.test.js +278 -0
- package/dist/sync/workspaceSyncModel.d.ts +4 -1
- package/dist/sync/workspaceSyncModel.js +9 -2
- package/dist/sync/workspaceSyncModel.test.js +29 -0
- package/dist/test/setup.js +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/ui/assets/{AgentsModule-Bdq3T1Ts.js → AgentsModule-CpsTmrIW.js} +1 -1
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-jKUVo-PJ.js → AnnotatedAttachmentWorkspace-C_TmXZwA.js} +1 -1
- package/dist/ui/assets/{DocumentWorkspace-DuQa-uIC.js → DocumentWorkspace-C3GyzrWm.js} +2 -2
- package/dist/ui/assets/{InitiativesModule-C8Pi2VTk.js → InitiativesModule-4-Rh2K2n.js} +1 -1
- package/dist/ui/assets/PlansPage-BP7AYOqr.js +1 -0
- package/dist/ui/assets/TaskSettings-BOC5F6Ag.js +8 -0
- package/dist/ui/assets/{TaskSettings-BwB9NtmJ.css → TaskSettings-CnIBL_Eb.css} +1 -1
- package/dist/ui/assets/{WorkflowsModule-b6TLuHwJ.js → WorkflowsModule-CGk9s3NJ.js} +1 -1
- package/dist/ui/assets/index-CLIMgR6g.js +6 -0
- package/dist/ui/assets/index-DneETxcu.css +1 -0
- package/dist/ui/assets/{vendor-icons-QZyhEwgT.js → vendor-icons-pWocEipT.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/accountProfileSummaryCache.d.ts +31 -0
- package/dist/utils/accountProfileSummaryCache.js +97 -0
- package/dist/utils/accountProfileSummaryCache.test.d.ts +1 -0
- package/dist/utils/accountProfileSummaryCache.test.js +63 -0
- package/dist/utils/taskActivity.js +17 -4
- package/dist/utils/taskActivity.test.js +27 -0
- package/dist/utils/taskNormalization.js +10 -2
- package/dist/utils/taskReferences.d.ts +11 -1
- package/dist/utils/taskReferences.js +33 -1
- package/package.json +4 -3
- package/scripts/qa-open-lib.mjs +175 -0
- package/scripts/qa-open-lib.mjs.d.ts +49 -0
- package/scripts/qa-open.mjs +352 -0
- package/dist/ui/assets/PlansPage-B6BDECSi.js +0 -1
- package/dist/ui/assets/TaskSettings-DUJgRTPU.js +0 -8
- package/dist/ui/assets/index-BiiF1cLQ.css +0 -1
- package/dist/ui/assets/index-xBWLPOEb.js +0 -6
package/dist/core/Taskforce.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ export interface TaskActor {
|
|
|
86
86
|
export interface TaskItem {
|
|
87
87
|
id: string;
|
|
88
88
|
referenceNumber?: number | null;
|
|
89
|
+
localReferenceNumber?: number | null;
|
|
89
90
|
referenceLabel?: string;
|
|
90
91
|
title: string;
|
|
91
92
|
description: string | null;
|
|
@@ -342,14 +343,10 @@ export interface InitiativeTemplate {
|
|
|
342
343
|
milestones: InitiativeTemplateMilestone[];
|
|
343
344
|
}
|
|
344
345
|
type WorkspaceSyncSettingsPayload = Record<string, Record<string, unknown>>;
|
|
345
|
-
type SignupMonetizationStrategy = 'auto_assign_default' | 'plan_selection_required';
|
|
346
|
-
interface SignupMonetizationSettings {
|
|
347
|
-
strategy: SignupMonetizationStrategy;
|
|
348
|
-
defaultSignupPlanVersionId: string | null;
|
|
349
|
-
}
|
|
350
346
|
type AccessRole = 'owner' | 'admin' | 'member' | 'read-only';
|
|
351
347
|
export type SystemRole = 'system_admin' | 'user';
|
|
352
348
|
type PermissionMode = 'read-only' | 'read-write';
|
|
349
|
+
type AuthTokenPurpose = 'email_verification' | 'password_reset' | 'invite_accept';
|
|
353
350
|
export type McpAccessTokenScope = 'tasks:read' | 'tasks:write' | 'workspace:read';
|
|
354
351
|
type McpAccessTokenStatus = 'active' | 'revoked' | 'expired';
|
|
355
352
|
export type McpOAuthProvider = 'chatgpt' | 'claude';
|
|
@@ -367,9 +364,24 @@ interface UserIdentityRecord {
|
|
|
367
364
|
userId: string;
|
|
368
365
|
email: string;
|
|
369
366
|
displayName?: string | null;
|
|
367
|
+
avatarUrl?: string | null;
|
|
370
368
|
systemRole?: SystemRole;
|
|
371
369
|
betaAccess?: boolean;
|
|
372
370
|
}
|
|
371
|
+
interface UserAvatarUploadDraftRecord {
|
|
372
|
+
draftId: string;
|
|
373
|
+
userId: string;
|
|
374
|
+
storageKey: string;
|
|
375
|
+
mimeType: string;
|
|
376
|
+
originalFilename: string;
|
|
377
|
+
sizeBytes: number;
|
|
378
|
+
storageProvider: 'local' | 'r2' | 'external';
|
|
379
|
+
finalizedAt?: string | null;
|
|
380
|
+
consumedAt?: string | null;
|
|
381
|
+
discardedAt?: string | null;
|
|
382
|
+
createdAt: string;
|
|
383
|
+
updatedAt: string;
|
|
384
|
+
}
|
|
373
385
|
interface WorkspaceUserRecord {
|
|
374
386
|
userId: string;
|
|
375
387
|
email: string;
|
|
@@ -437,6 +449,24 @@ interface SystemUserRecord {
|
|
|
437
449
|
updatedAt?: string | null;
|
|
438
450
|
emailVerifiedAt?: string | null;
|
|
439
451
|
}
|
|
452
|
+
export interface PurgedSystemUserSummary {
|
|
453
|
+
targetUserId: string;
|
|
454
|
+
email: string;
|
|
455
|
+
unassignedTaskCount: number;
|
|
456
|
+
clearedInitiativeOwnerCount: number;
|
|
457
|
+
clearedWorkstreamOwnerCount: number;
|
|
458
|
+
deletedWorkspaceMembershipCount: number;
|
|
459
|
+
deletedAuthTokenCount: number;
|
|
460
|
+
deletedAvatarDraftCount: number;
|
|
461
|
+
deletedMcpAccessTokenCount: number;
|
|
462
|
+
deletedMcpOauthAuthCodeCount: number;
|
|
463
|
+
deletedMcpOauthConnectorGrantCount: number;
|
|
464
|
+
deletedUiStateCount: number;
|
|
465
|
+
deletedUserPreferenceCount: number;
|
|
466
|
+
deletedEntitlementCount: number;
|
|
467
|
+
deletedUserBillingCount: number;
|
|
468
|
+
deletedUserCount: number;
|
|
469
|
+
}
|
|
440
470
|
export type SetupState = 'present' | 'missing' | 'unreadable';
|
|
441
471
|
export type RuntimeMode = 'local' | 'cloud';
|
|
442
472
|
export type WorkspaceMode = 'core' | 'operations';
|
|
@@ -476,6 +506,8 @@ interface CreateTaskOptions {
|
|
|
476
506
|
persistBackup?: boolean;
|
|
477
507
|
workspaceId?: string;
|
|
478
508
|
allowClientProvidedId?: boolean;
|
|
509
|
+
provisionalLocalReference?: boolean;
|
|
510
|
+
preferIncomingReferenceNumberOnConflict?: boolean;
|
|
479
511
|
skipRecompute?: boolean;
|
|
480
512
|
syncUpdatedAt?: string;
|
|
481
513
|
actorRef?: string;
|
|
@@ -511,7 +543,7 @@ interface McpAuditLogRecord {
|
|
|
511
543
|
reasonCode: string | null;
|
|
512
544
|
details: Record<string, unknown>;
|
|
513
545
|
}
|
|
514
|
-
export type EntitlementState = 'active' | 'trialing' | 'grace' | 'suspended' | 'canceled';
|
|
546
|
+
export type EntitlementState = 'pending_plan_selection' | 'checkout_pending' | 'active' | 'trialing' | 'grace' | 'suspended' | 'canceled';
|
|
515
547
|
export type PlanFeatureAccess = 'enabled' | 'disabled' | 'limited';
|
|
516
548
|
export interface PlanFeatureSnapshot {
|
|
517
549
|
featureKey: string;
|
|
@@ -573,6 +605,11 @@ interface PasswordAuthResult {
|
|
|
573
605
|
};
|
|
574
606
|
code?: 'INVALID_CREDENTIALS' | 'EMAIL_NOT_VERIFIED';
|
|
575
607
|
}
|
|
608
|
+
interface AuthTokenInspection {
|
|
609
|
+
state: 'valid' | 'expired' | 'used' | 'missing' | 'revoked';
|
|
610
|
+
userId?: string;
|
|
611
|
+
workspaceId?: string;
|
|
612
|
+
}
|
|
576
613
|
export interface McpAccessTokenRecord {
|
|
577
614
|
id: string;
|
|
578
615
|
workspaceId: string;
|
|
@@ -849,8 +886,20 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
849
886
|
getWorkspaceAssetStore(): WorkspaceAssetStore;
|
|
850
887
|
private normalizeEntitlementState;
|
|
851
888
|
private upsertCanonicalEntitlementRecord;
|
|
889
|
+
transitionCanonicalCommercialState(input: {
|
|
890
|
+
accountId: string;
|
|
891
|
+
planVersionId?: string | null;
|
|
892
|
+
state: EntitlementState;
|
|
893
|
+
effectiveAt?: string | null;
|
|
894
|
+
effectiveUntil?: string | null;
|
|
895
|
+
billingMirrorPlanId?: string | null;
|
|
896
|
+
source: 'registration' | 'checkout-start' | 'checkout-confirm' | 'stripe-webhook' | 'backfill' | 'legacy-plan-mode' | 'admin' | 'system';
|
|
897
|
+
updatedBy: string;
|
|
898
|
+
createdAt?: string | null;
|
|
899
|
+
updatedAt?: string | null;
|
|
900
|
+
}): import("./types.js").AccountEntitlementSnapshot;
|
|
852
901
|
private resolveWorkspaceLimitForUser;
|
|
853
|
-
private
|
|
902
|
+
private resolveRegistrationOnboardingOutcome;
|
|
854
903
|
createUserBillingRecord(userId: string, options?: {
|
|
855
904
|
entitlementState?: string;
|
|
856
905
|
planId?: string | null;
|
|
@@ -940,8 +989,11 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
940
989
|
hasProjectThemeOverride(workspaceId?: string, userId?: string): boolean;
|
|
941
990
|
getEffectiveTheme(workspaceId?: string, userId?: string): TaskforceTheme;
|
|
942
991
|
hasProjectJsonBackupOverride(workspaceId?: string, userId?: string): boolean;
|
|
943
|
-
|
|
944
|
-
|
|
992
|
+
getOnboardingPolicy(): import("./types.js").OnboardingPolicy;
|
|
993
|
+
validateOnboardingPolicy(input?: {
|
|
994
|
+
mode?: 'require_plan_selection' | 'auto_grant_free' | 'auto_start_trial';
|
|
995
|
+
planVersionId?: string | null;
|
|
996
|
+
}): import("./types.js").OnboardingPolicyValidationResult;
|
|
945
997
|
updateGlobalSettings(settings: GlobalTaskforceSettings): void;
|
|
946
998
|
private sanitizeUserGlobalSyncSettings;
|
|
947
999
|
getUserGlobalSyncSettings(userId: string): {
|
|
@@ -971,7 +1023,9 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
971
1023
|
private rowToWorkstream;
|
|
972
1024
|
private rowToChecklistItem;
|
|
973
1025
|
private sanitizeTaskReferenceNumber;
|
|
1026
|
+
private getTaskReferencePolicyDeps;
|
|
974
1027
|
private getTaskByReferenceNumber;
|
|
1028
|
+
private getTaskByLocalReferenceNumber;
|
|
975
1029
|
resolveTaskIdentifier(value: string, workspaceId?: string): TaskItem | null;
|
|
976
1030
|
getInitiative(id: string, workspaceId?: string): InitiativeItem | null;
|
|
977
1031
|
listInitiatives(workspaceId?: string): InitiativeItem[];
|
|
@@ -989,6 +1043,15 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
989
1043
|
upsertWorkstreamForSync(workstream: WorkstreamItem, workspaceId?: string | null): WorkstreamItem;
|
|
990
1044
|
listChecklistItems(taskId: string, workspaceId?: string): ChecklistItem[];
|
|
991
1045
|
replaceChecklistItems(taskId: string, items: Array<Partial<ChecklistItem>>, workspaceId?: string): ChecklistItem[];
|
|
1046
|
+
private getTaskReferenceSequenceValue;
|
|
1047
|
+
private getLocalTaskReferenceSequenceValue;
|
|
1048
|
+
private getMaxTaskReferenceNumber;
|
|
1049
|
+
private getMaxLocalTaskReferenceNumber;
|
|
1050
|
+
private persistTaskReferenceSequence;
|
|
1051
|
+
private persistLocalTaskReferenceSequence;
|
|
1052
|
+
private allocateNextTaskReferenceNumber;
|
|
1053
|
+
private allocateNextLocalTaskReferenceNumber;
|
|
1054
|
+
private relocateTaskReferenceConflict;
|
|
992
1055
|
private reserveTaskReferenceNumber;
|
|
993
1056
|
private reserveGenericReferenceNumber;
|
|
994
1057
|
private reserveInitiativeReferenceNumber;
|
|
@@ -1081,7 +1144,25 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
1081
1144
|
}): UserAccessRecord;
|
|
1082
1145
|
resolveUserAccess(userId: string, workspaceId: string, fallbackRole?: AccessRole): UserAccessRecord | null;
|
|
1083
1146
|
resolveUserIdentity(userId: string): UserIdentityRecord | null;
|
|
1147
|
+
updateUserProfile(userId: string, input: {
|
|
1148
|
+
displayName: string;
|
|
1149
|
+
avatarUrl?: string | null;
|
|
1150
|
+
}): UserIdentityRecord | null;
|
|
1084
1151
|
updateUserDisplayName(userId: string, displayName: string): UserIdentityRecord | null;
|
|
1152
|
+
createUserAvatarUploadDraft(input: {
|
|
1153
|
+
userId: string;
|
|
1154
|
+
draftId: string;
|
|
1155
|
+
storageKey: string;
|
|
1156
|
+
mimeType: string;
|
|
1157
|
+
originalFilename: string;
|
|
1158
|
+
sizeBytes: number;
|
|
1159
|
+
storageProvider?: 'local' | 'r2' | 'external';
|
|
1160
|
+
}): UserAvatarUploadDraftRecord;
|
|
1161
|
+
getUserAvatarUploadDraft(userId: string, draftId: string): UserAvatarUploadDraftRecord | null;
|
|
1162
|
+
markUserAvatarUploadDraftFinalized(userId: string, draftId: string): UserAvatarUploadDraftRecord | null;
|
|
1163
|
+
markUserAvatarUploadDraftConsumed(userId: string, draftId: string): UserAvatarUploadDraftRecord | null;
|
|
1164
|
+
discardUserAvatarUploadDraft(userId: string, draftId: string): UserAvatarUploadDraftRecord | null;
|
|
1165
|
+
cleanupStaleUserAvatarUploadDrafts(userId: string, olderThanIso: string): UserAvatarUploadDraftRecord[];
|
|
1085
1166
|
getSystemRole(userId: string): SystemRole;
|
|
1086
1167
|
getUserBetaAccess(userId: string): boolean;
|
|
1087
1168
|
countSystemAdmins(): number;
|
|
@@ -1090,6 +1171,11 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
1090
1171
|
setSystemRole(userId: string, role: SystemRole): boolean;
|
|
1091
1172
|
setUserDisabledGlobal(userId: string, disabled: boolean): boolean;
|
|
1092
1173
|
setUserBetaAccessGlobal(userId: string, enabled: boolean): boolean;
|
|
1174
|
+
purgeSystemUser(input: {
|
|
1175
|
+
targetUserId: string;
|
|
1176
|
+
actorUserId: string;
|
|
1177
|
+
emailConfirmation: string;
|
|
1178
|
+
}): PurgedSystemUserSummary;
|
|
1093
1179
|
private clearActiveAssignmentsForUnavailableActor;
|
|
1094
1180
|
listWorkspaceUsers(workspaceId: string): WorkspaceUserRecord[];
|
|
1095
1181
|
replaceWorkspaceUsersForSync(input: {
|
|
@@ -1424,10 +1510,12 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
1424
1510
|
workspaceId: string | null;
|
|
1425
1511
|
role: AccessRole;
|
|
1426
1512
|
planSelectionRequired: boolean;
|
|
1513
|
+
checkoutPending: boolean;
|
|
1514
|
+
commercialState: EntitlementState;
|
|
1427
1515
|
};
|
|
1428
1516
|
private createOneTimeAuthToken;
|
|
1429
1517
|
private consumeOneTimeAuthToken;
|
|
1430
|
-
|
|
1518
|
+
inspectOneTimeAuthToken(token: string, purpose: AuthTokenPurpose): AuthTokenInspection;
|
|
1431
1519
|
revokeMcpCredentialsForUserWorkspace(userId: string, workspaceId: string, revokedByUserId?: string | null): void;
|
|
1432
1520
|
private revokeMcpCredentialsForWorkspace;
|
|
1433
1521
|
listMcpAccessTokens(input: {
|
|
@@ -1602,9 +1690,11 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
|
|
|
1602
1690
|
validateOnly?: boolean;
|
|
1603
1691
|
workspaceId?: string;
|
|
1604
1692
|
allowClientProvidedId?: boolean;
|
|
1693
|
+
provisionalLocalReference?: boolean;
|
|
1605
1694
|
}): BulkCreateTaskResult;
|
|
1606
1695
|
updateTask(id: string, updates: Partial<TaskItem>, workspaceId?: string, options?: {
|
|
1607
1696
|
persistBackup?: boolean;
|
|
1697
|
+
preferIncomingReferenceNumberOnConflict?: boolean;
|
|
1608
1698
|
skipRecompute?: boolean;
|
|
1609
1699
|
syncUpdatedAt?: string;
|
|
1610
1700
|
actorRef?: string;
|
|
@@ -80,6 +80,139 @@ describe('TaskforceCore id policy', () => {
|
|
|
80
80
|
cleanup();
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
|
+
it('assigns provisional local task references without consuming canonical task references', () => {
|
|
84
|
+
const { core, cleanup } = makeCore();
|
|
85
|
+
try {
|
|
86
|
+
const provisionalFirst = core.createTask({ title: 'Offline first' }, {
|
|
87
|
+
workspaceId: 'workspace-a',
|
|
88
|
+
provisionalLocalReference: true
|
|
89
|
+
});
|
|
90
|
+
const provisionalSecond = core.createTask({ title: 'Offline second' }, {
|
|
91
|
+
workspaceId: 'workspace-a',
|
|
92
|
+
provisionalLocalReference: true
|
|
93
|
+
});
|
|
94
|
+
const canonical = core.createTask({ title: 'Cloud-backed task' }, { workspaceId: 'workspace-a' });
|
|
95
|
+
expect(provisionalFirst.referenceNumber).toBeNull();
|
|
96
|
+
expect(provisionalFirst.localReferenceNumber).toBe(1);
|
|
97
|
+
expect(provisionalFirst.referenceLabel).toBe('LT-1');
|
|
98
|
+
expect(provisionalSecond.referenceNumber).toBeNull();
|
|
99
|
+
expect(provisionalSecond.localReferenceNumber).toBe(2);
|
|
100
|
+
expect(provisionalSecond.referenceLabel).toBe('LT-2');
|
|
101
|
+
expect(canonical.referenceNumber).toBe(1);
|
|
102
|
+
expect(canonical.localReferenceNumber).toBeNull();
|
|
103
|
+
expect(canonical.referenceLabel).toBe('T-1');
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
cleanup();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
it('replaces a provisional local reference with a canonical cloud reference during sync apply', () => {
|
|
110
|
+
const { core, cleanup } = makeCore();
|
|
111
|
+
try {
|
|
112
|
+
const provisional = core.createTask({ title: 'Offline draft' }, {
|
|
113
|
+
workspaceId: 'workspace-a',
|
|
114
|
+
provisionalLocalReference: true
|
|
115
|
+
});
|
|
116
|
+
expect(provisional.referenceLabel).toBe('LT-1');
|
|
117
|
+
const syncResult = core.applyWorkspaceSyncSnapshot({
|
|
118
|
+
tasks: [
|
|
119
|
+
{
|
|
120
|
+
id: provisional.id,
|
|
121
|
+
title: 'Offline draft',
|
|
122
|
+
status: 'task',
|
|
123
|
+
referenceNumber: 7,
|
|
124
|
+
updatedAt: '2099-04-10T17:00:00.000Z'
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}, 'workspace-a');
|
|
128
|
+
expect(syncResult.updated).toBe(1);
|
|
129
|
+
expect(core.getTask(provisional.id, 'workspace-a')).toEqual(expect.objectContaining({
|
|
130
|
+
referenceNumber: 7,
|
|
131
|
+
localReferenceNumber: null,
|
|
132
|
+
referenceLabel: 'T-7'
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
cleanup();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
it('preserves provisional local references across core reloads', () => {
|
|
140
|
+
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'taskforce-id-reload-test-'));
|
|
141
|
+
const storagePath = path.join(projectRoot, '.taskforce');
|
|
142
|
+
const firstCore = new TaskforceCore({ projectRoot, storagePath });
|
|
143
|
+
try {
|
|
144
|
+
const provisional = firstCore.createTask({ title: 'Offline draft' }, {
|
|
145
|
+
workspaceId: 'workspace-a',
|
|
146
|
+
provisionalLocalReference: true
|
|
147
|
+
});
|
|
148
|
+
expect(provisional.referenceNumber).toBeNull();
|
|
149
|
+
expect(provisional.localReferenceNumber).toBe(1);
|
|
150
|
+
firstCore.close();
|
|
151
|
+
const reloadedCore = new TaskforceCore({ projectRoot, storagePath });
|
|
152
|
+
try {
|
|
153
|
+
const reloadedTask = reloadedCore.getTask(provisional.id, 'workspace-a');
|
|
154
|
+
expect(reloadedTask).toEqual(expect.objectContaining({
|
|
155
|
+
referenceNumber: null,
|
|
156
|
+
localReferenceNumber: 1,
|
|
157
|
+
referenceLabel: 'LT-1'
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
reloadedCore.close();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
it('lets the incoming synced task keep its preferred reference and renumbers the local incumbent', () => {
|
|
169
|
+
const { core, cleanup } = makeCore();
|
|
170
|
+
try {
|
|
171
|
+
const localTask = core.createTask({ title: 'Local task' }, { workspaceId: 'workspace-a' });
|
|
172
|
+
const syncResult = core.applyWorkspaceSyncSnapshot({
|
|
173
|
+
tasks: [
|
|
174
|
+
{
|
|
175
|
+
id: 'task-sync-imported-collision',
|
|
176
|
+
title: 'Remote task',
|
|
177
|
+
status: 'task',
|
|
178
|
+
referenceNumber: localTask.referenceNumber,
|
|
179
|
+
createdAt: '2026-04-10T15:00:00.000Z',
|
|
180
|
+
updatedAt: '2026-04-10T15:00:00.000Z',
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}, 'workspace-a');
|
|
184
|
+
expect(syncResult.created).toBe(1);
|
|
185
|
+
expect(core.getTask(localTask.id, 'workspace-a')?.referenceLabel).toBe('T-2');
|
|
186
|
+
expect(core.getTask('task-sync-imported-collision', 'workspace-a')?.referenceLabel).toBe('T-1');
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
cleanup();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
it('lets incoming synced updates claim the preferred reference and renumbers the displaced task', () => {
|
|
193
|
+
const { core, cleanup } = makeCore();
|
|
194
|
+
try {
|
|
195
|
+
const first = core.createTask({ title: 'First' }, { workspaceId: 'workspace-a' });
|
|
196
|
+
const second = core.createTask({ title: 'Second' }, { workspaceId: 'workspace-a' });
|
|
197
|
+
const syncResult = core.applyWorkspaceSyncSnapshot({
|
|
198
|
+
tasks: [
|
|
199
|
+
{
|
|
200
|
+
id: second.id,
|
|
201
|
+
title: 'Second',
|
|
202
|
+
status: 'task',
|
|
203
|
+
referenceNumber: first.referenceNumber,
|
|
204
|
+
updatedAt: '2099-04-11T16:00:00.000Z',
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
}, 'workspace-a');
|
|
208
|
+
expect(syncResult.updated).toBe(1);
|
|
209
|
+
expect(core.getTask(first.id, 'workspace-a')?.referenceLabel).toBe('T-3');
|
|
210
|
+
expect(core.getTask(second.id, 'workspace-a')?.referenceLabel).toBe('T-1');
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
cleanup();
|
|
214
|
+
}
|
|
215
|
+
});
|
|
83
216
|
it('resolves task identifiers by task reference or internal id', () => {
|
|
84
217
|
const { core, cleanup } = makeCore();
|
|
85
218
|
try {
|