fix(sync): a trashed entry is no longer resurrected as a duplicate
The trash is a soft delete: no tombstone is written and the rows are absent from state.entries, so the merge read their uuids as missing locally and POSTed them back as fresh live entries. Trashing 30 entries then syncing produced 30 live duplicates alongside the trashed originals - two rows sharing one uuid. applyRemoteSnapshot now loads the trash and skips any uuid found there. Emptying the trash is what writes the tombstone that propagates the delete.
This commit is contained in:
+9
-1
@@ -233,6 +233,14 @@ plus bas.
|
||||
- **ACTION** : importer un CSV sans colonnes favorite/pinned.
|
||||
- **ATTENDU** : entrées importées ni épinglées ni favorites (défaut 0), pas d'erreur.
|
||||
|
||||
### F8 · mettre à la corbeille puis synchroniser ne duplique pas ✅
|
||||
- **ACTION** : synchroniser une première fois (l'instantané distant contient les entrées) → mettre **plusieurs** entrées à la corbeille → **Sync now**.
|
||||
- **ATTENDU** : les entrées restent en corbeille, et **rien n'est recréé** dans la liste vivante. Le résumé ne doit pas annoncer `pulled N new`.
|
||||
- **Le bug** : 30 entrées mises à la corbeille puis un sync → 30 **doublons vivants** à côté des originaux en corbeille, soit deux lignes partageant un même `uuid`.
|
||||
- **Cause** : la corbeille est une suppression **douce**, sans tombstone (seul le hard-delete en écrit un), et les entrées supprimées sont absentes de `state.entries`. Le merge voyait donc leurs uuid comme « absents en local » et les repostait comme des entrées neuves.
|
||||
- **Correctif** : `applyRemoteSnapshot` charge aussi la corbeille et saute tout uuid qui s'y trouve. La décision locale de mettre à la corbeille l'emporte ; c'est le **vidage** de la corbeille qui écrit le tombstone et propage la suppression.
|
||||
- **Nettoyage si le bug a déjà frappé** : les doublons vivants sont à supprimer à la main. Vérifier aussi l'autre appareil, où ils ont pu être poussés.
|
||||
|
||||
### F4 · le sync ne propage PAS les drapeaux (device-local, décidé 2026-07-11)
|
||||
- **ACTION** : épingler/favoriser une entrée sur le device A → *Sync now* → *Sync now* sur le device B.
|
||||
- **ATTENDU** : sur B, l'entrée **n'est pas** épinglée/favorite. Et un sync ne doit jamais **retirer** un drapeau posé localement sur B (le PUT serveur ne touche pas ces colonnes).
|
||||
@@ -366,7 +374,7 @@ ou le déchiffrement.
|
||||
- **Après le test** : supprimer les dumps. Ils contiennent des secrets en clair, sans chiffrement.
|
||||
- **Validation fonctionnelle obligatoire** — les **quatre** chemins qui lisent encore un secret, à repasser après toute modification de `loadAutoBackupConfig` / `loadSyncConfig` : *Backup now* **puis import du fichier produit** (le fichier seul ne prouve rien, cf. F2) · *Test connection* WebDAV **avec authentification** · *Sync now* (le compteur `updated` prouve que l'instantané distant a été **déchiffré**, pas seulement téléchargé) · le backup planifié au déverrouillage.
|
||||
- **Monter un WebDAV authentifié pour le test** : `python -m wsgidav.server.server_cli -c <config.json>` avec `simple_dc.user_mapping` et **`accept_basic: true`, `accept_digest: false`** — notre client n'envoie que du Basic. Le partage ne doit plus être marqué `(anonymous)` au démarrage. Un premier 401 suivi d'un 200 authentifié dans le journal est **normal** : WinHTTP n'envoie les identifiants qu'après le défi.
|
||||
- **Piège de saisie** : les champs identifiant / mot de passe n'enregistrent que sur `change` (perte du focus). Taper puis cliquer aussitôt sur *Test connection* peut lire la préférence avant son écriture — les deux passent par des navigations `cmd://`, qui se coalescent. Faire Tab avant de cliquer.
|
||||
- **Piège de saisie** : les champs identifiant / mot de passe n'enregistrent que sur `change` (perte du focus). Taper puis cliquer aussitôt sur *Test connection* peut lire la préférence avant son écriture — les deux passent par des navigations `cmd://`, qui se coalescent. Faire Tab avant de cliquer. **python -m wsgidav.server.server_cli -c "e:\webdav.json"**
|
||||
|
||||
### E5 · la clé du coffre n'est plus en clair dans le web storage ✅
|
||||
- **ACTION** : coffre déverrouillé → console WebView2 :
|
||||
|
||||
Reference in New Issue
Block a user