mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-25 00:47:39 +00:00
* fix(sync): never upload plaintext ops for E2EE-mandatory providers SuperSync's first-time setup ran an initial sync (dialog-sync-cfg save -> sync(true)) BEFORE the user chose an encryption password, so all local ops (incl. issue-provider credentials) were uploaded to the server in cleartext. Completing setup deleted them; aborting left them stored indefinitely, breaking the E2EE promise (GHSA-9v8x-68pf-p5x7). Add an optional `isEncryptionMandatory` capability to OperationSyncCapable (true for SuperSync) and refuse to upload in the op-log upload path while no usable key is configured. Downloads still run (merge-first) and the encryption- enable flow performs the first, encrypted upload, so the setup flow and prompt are unchanged. File-based providers, where unencrypted sync is a legitimate user choice, leave the flag unset. * fix(sync): fail closed on plaintext snapshot for E2EE-mandatory providers Multi-review hardening for GHSA-9v8x-68pf-p5x7. The op-upload guard closes the reported leak, but SnapshotUploadService.deleteAndReuploadWithNewEncryption could still push a plaintext snapshot for SuperSync on two adjacent paths: the (today UI-unreachable) disable-encryption flow, and a keyless import declaring isEncryptionEnabled:true. Reject an unencrypted snapshot for an encryption- mandatory provider before any destructive deleteAllData, so the "never transmit plaintext" invariant holds regardless of caller. Also lower the mandatory-encryption upload-skip log from warn to normal: it is an expected by-design skip during the pre-encryption setup window and would otherwise fire on every auto-sync cycle. * fix(sync): consolidate op-log into the encryption-enable snapshot Follow-up to the GHSA-9v8x-68pf-p5x7 upload guard. With the guard, first-time SuperSync setup leaves the whole local history unsynced until encryption is enabled; the enable-snapshot then represents that full state, but the ops were re-uploaded incrementally on top of it on the next sync (redundant server op-log bloat, and previously untested at whole-history volume). deleteAndReuploadWithNewEncryption now captures the pending ops the snapshot subsumes (before the destructive delete, under runWithSyncBlocked + a modal dialog so the set is stable) and marks them synced after a successful upload — mirroring planRegularOpsAfterFullStateUpload in the op-log upload path, which this direct snapshot upload bypasses. Also fixes the same latent redundancy in the enable-from-settings-with-pending-ops flow. Adds a multi-client e2e: local task history exists before first-time encrypted setup, then a second client with the same password receives exactly those tasks with no duplicates, conflicts, or errors. * ci(e2e): add optional grep input to manual SuperSync e2e dispatch * fix(sync): capture subsumed ops before state snapshot to prevent mark-synced data loss deleteAndReuploadWithNewEncryption captured getUnsynced() AFTER the full-state snapshot, so an op created in that window was marked synced yet absent from the snapshot — silently lost. Capture the unsynced set first: every marked-synced op is then guaranteed present in the snapshot, and a concurrent op arriving after the capture is left unsynced and re-uploaded next sync (idempotent by op id). * test(sync): mock WebCrypto so mandatory-encryption guard test reaches the guard The 'enabling without a usable key' case passed isEncryptionEnabled: true but did not mock WebCrypto, so the availability check threw WebCryptoNotAvailableError in non-secure CI before the /unencrypted snapshot/ guard under test. |
||
|---|---|---|
| .. | ||
| ENCRYPTION-E2E-STATUS.md | ||
| import-sync.spec.ts | ||
| supersync-account-deletion.spec.ts | ||
| supersync-account-reset.spec.ts | ||
| supersync-advanced-edge-cases.spec.ts | ||
| supersync-advanced.spec.ts | ||
| supersync-archive-conflict.spec.ts | ||
| supersync-archive-data-sync.spec.ts | ||
| supersync-archive-subtasks.spec.ts | ||
| supersync-backup-import-id-mismatch.spec.ts | ||
| supersync-backup-recovery.spec.ts | ||
| supersync-cascade-delete.spec.ts | ||
| supersync-compaction.spec.ts | ||
| supersync-concurrent-delete-reorder.spec.ts | ||
| supersync-concurrent-import.spec.ts | ||
| supersync-constraint-error-recovery.spec.ts | ||
| supersync-cross-entity.spec.ts | ||
| supersync-daily-summary.spec.ts | ||
| supersync-day-change-overdue-6992.spec.ts | ||
| supersync-divergence-bug-6571.spec.ts | ||
| supersync-edge-cases.spec.ts | ||
| supersync-encryption-conflict.spec.ts | ||
| supersync-encryption-password-change.spec.ts | ||
| supersync-encryption-password-preservation.spec.ts | ||
| supersync-encryption.spec.ts | ||
| supersync-error-handling.spec.ts | ||
| supersync-error-scenarios.spec.ts | ||
| supersync-example-task-fresh-client.spec.ts | ||
| supersync-global-config-edge-cases.spec.ts | ||
| supersync-import-clean-server-state.spec.ts | ||
| supersync-import-clean-slate.spec.ts | ||
| supersync-import-conflict-dialog.spec.ts | ||
| supersync-import-encryption-change.spec.ts | ||
| supersync-import-encryption-preserve.spec.ts | ||
| supersync-import-other-client-ops.spec.ts | ||
| supersync-import-same-client-ops.spec.ts | ||
| supersync-keep-local-archive-preservation.spec.ts | ||
| supersync-lastseq-preservation.spec.ts | ||
| supersync-late-join.spec.ts | ||
| supersync-legacy-migration-sync.spec.ts | ||
| supersync-lww-conflict.spec.ts | ||
| supersync-lww-singleton.spec.ts | ||
| supersync-max-retry-rejection.spec.ts | ||
| supersync-models.spec.ts | ||
| supersync-multi-tab.spec.ts | ||
| supersync-network-failure.spec.ts | ||
| supersync-no-op-sync.spec.ts | ||
| supersync-planner.spec.ts | ||
| supersync-provider-switch-to-supersync.spec.ts | ||
| supersync-provider-switch.spec.ts | ||
| supersync-realtime-push.spec.ts | ||
| supersync-reenable-and-account-switch.spec.ts | ||
| supersync-rejected-ops-transient-download-8331.spec.ts | ||
| supersync-repeat-task-advanced.spec.ts | ||
| supersync-repeat-task.spec.ts | ||
| supersync-server-backup-revert.spec.ts | ||
| supersync-server-migration-abort.spec.ts | ||
| supersync-server-migration.spec.ts | ||
| supersync-simple-counter-delete-update-7330.spec.ts | ||
| supersync-simple-counter.spec.ts | ||
| supersync-snapshot-vector-clock.spec.ts | ||
| supersync-stress.spec.ts | ||
| supersync-superseded-clock-regression.spec.ts | ||
| supersync-task-ordering.spec.ts | ||
| supersync-time-tracking-advanced.spec.ts | ||
| supersync-token-expiry.spec.ts | ||
| supersync-vector-clock-max-size.spec.ts | ||
| supersync-vector-clock-pruning.spec.ts | ||
| supersync-worklog.spec.ts | ||
| supersync-wrong-password-error.spec.ts | ||
| supersync.spec.ts | ||
| webdav-conflict-use-remote-restore-8107.spec.ts | ||
| webdav-encryption-conflict-use-local.spec.ts | ||
| webdav-encryption-disable.spec.ts | ||
| webdav-first-sync-conflict.spec.ts | ||
| webdav-legacy-migration-sync.spec.ts | ||
| webdav-provider-switch.spec.ts | ||
| webdav-single-client-rapid-sync.spec.ts | ||
| webdav-sync-advanced.spec.ts | ||
| webdav-sync-archive.spec.ts | ||
| webdav-sync-delete-cascade.spec.ts | ||
| webdav-sync-error-handling.spec.ts | ||
| webdav-sync-expansion.spec.ts | ||
| webdav-sync-full.spec.ts | ||
| webdav-sync-tags.spec.ts | ||
| webdav-sync-task-order.spec.ts | ||
| webdav-sync-today-tag.spec.ts | ||