fix: resolve sync data inconsistency between mobile and web (#55) #58

Merged
maximus merged 1 commit from fix/simpl-liste-55-sync-data-inconsistency into master 2026-04-08 19:32:16 +00:00
Owner

Fixes #55

Problème

Les données entre mobile et web étaient incohérentes : tâches complétées sur mobile apparaissaient non-complétées sur web, nouvelles tâches non synchronisées, Sync Now silencieusement cassé.

Causes racines

  1. Format GET /api/sync — API retournait des entités brutes mais le client mobile attendait {changes: [...], sync_token}. pullChanges() itérait data.changes qui était undefined.
  2. snake_case vs camelCase — Outbox mobile envoyait due_date, list_id, task_tag mais le serveur attend dueDate, listId, taskTag (Drizzle camelCase).
  3. completedAt manquant — Jamais inclus dans les payloads outbox, donc la completion était perdue au sync.

Corrections

  • API GET transforme maintenant les entités en format SyncPullChange
  • Tous les outbox writes utilisent camelCase
  • completedAt ajouté aux payloads create et update
  • Conversion Date pour completedAt côté serveur
  • id retiré du payload d'update pour éviter d'écraser la PK
Fixes #55 ## Problème Les données entre mobile et web étaient incohérentes : tâches complétées sur mobile apparaissaient non-complétées sur web, nouvelles tâches non synchronisées, Sync Now silencieusement cassé. ## Causes racines 1. **Format GET /api/sync** — API retournait des entités brutes mais le client mobile attendait `{changes: [...], sync_token}`. `pullChanges()` itérait `data.changes` qui était `undefined`. 2. **snake_case vs camelCase** — Outbox mobile envoyait `due_date`, `list_id`, `task_tag` mais le serveur attend `dueDate`, `listId`, `taskTag` (Drizzle camelCase). 3. **`completedAt` manquant** — Jamais inclus dans les payloads outbox, donc la completion était perdue au sync. ## Corrections - API GET transforme maintenant les entités en format `SyncPullChange` - Tous les outbox writes utilisent camelCase - `completedAt` ajouté aux payloads create et update - Conversion Date pour `completedAt` côté serveur - `id` retiré du payload d'update pour éviter d'écraser la PK
maximus added 1 commit 2026-04-08 19:28:52 +00:00
Three root causes fixed:

1. API GET /api/sync returned raw entities but mobile client expected
   {changes: [...], sync_token} format — pullChanges() iterated
   data.changes which was undefined, silently skipping all server data.
   Now transforms entities into the SyncPullChange format.

2. Mobile outbox writes used snake_case keys (due_date, list_id, etc.)
   but server processOperation spreads data directly into Drizzle which
   expects camelCase (dueDate, listId). Fixed all outbox writes to use
   camelCase. Also fixed task_tag → taskTag entity type.

3. Missing completedAt in task outbox payloads — completion state was
   lost during sync. Added completedAt to both create and update outbox
   entries, and added Date conversion in server update handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Review — APPROVE

3 causes racines corrigées pour la sync mobile ↔ web :

  1. Format GET /api/sync — Transforme les entités brutes en format {changes, sync_token} attendu par pullChanges()
  2. snake_case → camelCase — Outbox writes alignés avec Drizzle schema server (dueDate, listId, taskTag)
  3. completedAt manquant — Ajouté dans outbox + conversion Date côté serveur

Bonus défensif : delete raw.id empêche l'écrasement de la PK dans les updates.

Note non-bloquante : slTags n'a pas de colonne updatedAt, donc createdAt est utilisé comme proxy dans le GET.

🤖 Review automatique par sprint

## Review — APPROVE ✅ 3 causes racines corrigées pour la sync mobile ↔ web : 1. **Format GET /api/sync** — Transforme les entités brutes en format `{changes, sync_token}` attendu par `pullChanges()` 2. **snake_case → camelCase** — Outbox writes alignés avec Drizzle schema server (`dueDate`, `listId`, `taskTag`) 3. **completedAt manquant** — Ajouté dans outbox + conversion Date côté serveur Bonus défensif : `delete raw.id` empêche l'écrasement de la PK dans les updates. **Note non-bloquante** : `slTags` n'a pas de colonne `updatedAt`, donc `createdAt` est utilisé comme proxy dans le GET. 🤖 Review automatique par sprint
maximus merged commit 0893cea489 into master 2026-04-08 19:32:16 +00:00
maximus deleted branch fix/simpl-liste-55-sync-data-inconsistency 2026-04-08 19:32:16 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/simpl-liste#58
No description provided.