Comfy-Org / Comfy-Org/ComfyUI_frontend
Workflow draft restore lacks auth-subject and CRDT-lineage isolation
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 699
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 490
Description
Current `main` still keys V2 workflow draft records by only `workspaceId + hash(path)`, and payloads carry `data` plus `updatedAt` with no authenticated subject, stable workflow UUID, CRDT lineage id, or base-state vector. That means a later restore can select a draft for the same workspace/path without proving it belongs to the current authenticated principal or current document lineage.
The narrowed current risk is not ordinary logout: `useWorkflowPersistenceV2` now clears restorable workflow storage on logout and `storageIO` blocks stale writes during that transition. The remaining gap is direct identity change / same browser profile and future CRDT lineage reset. `useCurrentUser().onUserLogout` only fires when `resolvedUserInfo` transitions from a user to `null`, while `authStore` handles direct A -> B identity change without routing workflow draft storage through that logout cleanup. Separately, restore has no lineage/base-vector gate, so old-lineage draft bytes cannot be distinguished from same-lineage recoverable edits.
Verified on frontend `main` at `f954e479a37b168a9596aa05a1ce1dec1e9a93b4`:
- `src/platform/workflow/persistence/base/storageKeys.ts`: `getWorkspaceId()` returns a workspace id or literal `personal`; V2 keys are `Comfy.Workflow.DraftIndex.v2:${workspaceId}` and `Comfy.Workflow.Draft.v2:${workspaceId}:${hash(path)}`.
- `src/platform/workflow/persistence/stores/workflowDraftStoreV2.ts`: `saveDraft` and `getDraft` address records by the current workspace and path hash only.
- `src/platform/workflow/persistence/base/draftTypes.ts`: draft payload metadata is content and timestamp, not subject/lineage/base-vector.
- `src/composables/auth/useCurrentUser.ts`: `onUserLogout` calls back only for `prevUser && !user`.
- `src/stores/authStore.ts`: direct identity change is detected and resets workspace/socket state, but does not explicitly clear or re-key workflow draft storage.
- `src/platform/workflow/persistence/composables/useWorkflowPersistenceV2.ts`: cleanup is registered on `onUserLogout`; restore uses session path or latest draft without subject/lineage validation.
Suggested fix shape: make the draft identity include a canonical auth subject and document lineage metadata, or at minimum clear/detach workflow draft storage on every authenticated subject change before rendering the next user's context. Add regression coverage for direct A -> B identity change, not just user -> null logout, and keep ordinary same-user token refresh/reconnect preserving drafts.
Program evidence: `reports/spikes/spike-7-draft-storage-spec.md`, `logs/RISK-REGISTER.md` `R-50`, and `todo.md` `r50-1`.
Contributor guide
Research direction
Start with src/platform/workflow/persistence/base/storageKeys.ts, draftTypes.ts, stores/workflowDraftStoreV2.ts, and composables/useWorkflowPersistenceV2.ts, then trace the direct identity-change handling in src/stores/authStore.ts and src/composables/auth/useCurrentUser.ts. Done means drafts cannot cross authenticated subjects or document lineages, direct A → B changes have regression coverage, and same-user refresh or reconnect preserves drafts.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authentication, frontend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100