Reported during QA session.
What's wrong
The mobile sync engine has no conflict resolution strategy. When the same record has been changed both locally on the device and remotely on the server since the last pull, there is no defined rule for which change wins — the outcome depends on the order pull and push happen to run, so a user's local edit can be silently overwritten, or a server-side change can be silently clobbered by a stale local one.
This matters most for records that both sides legitimately write: peer/profile details, conversation and message read state, and anything an admin can change server-side while the device is offline.
What I expected
Sync should have an explicit, documented conflict policy that is applied consistently on every pull, so the same conflicting inputs always produce the same result and no accepted local change is lost without a trace.
Proposed change
- Define a per-collection conflict policy (last-write-wins on a trusted timestamp is the likely default; some collections may need field-level merge or server-authoritative rules).
- Detect the conflict case explicitly during pull — a record that changed remotely and also has unpushed local changes — instead of letting write ordering decide.
- Log conflicts so they can be observed in QA rather than only noticed as missing data.
- Document the chosen policy per collection alongside the sync documentation.
Steps to reproduce
- Log in on the mobile app and let it sync.
- Put the device offline and edit a record locally (e.g. change a profile detail).
- While the device is still offline, change the same record from the admin dashboard.
- Bring the device back online and let sync run.
- Observe that the winning value is not predictable and the losing change is discarded with no indication.
Additional context
The pull path normalizes server records and applies them locally, and the push path builds a payload from locally changed records — but neither step compares the two sides for a genuine conflict. Any fix needs to be consistent with the epoch-millisecond sync timestamp convention used across the sync API.
Related: existing sync defects where records are dropped or skipped are tracked separately and should not be folded into this work.
Reported during QA session.
What's wrong
The mobile sync engine has no conflict resolution strategy. When the same record has been changed both locally on the device and remotely on the server since the last pull, there is no defined rule for which change wins — the outcome depends on the order pull and push happen to run, so a user's local edit can be silently overwritten, or a server-side change can be silently clobbered by a stale local one.
This matters most for records that both sides legitimately write: peer/profile details, conversation and message read state, and anything an admin can change server-side while the device is offline.
What I expected
Sync should have an explicit, documented conflict policy that is applied consistently on every pull, so the same conflicting inputs always produce the same result and no accepted local change is lost without a trace.
Proposed change
Steps to reproduce
Additional context
The pull path normalizes server records and applies them locally, and the push path builds a payload from locally changed records — but neither step compares the two sides for a genuine conflict. Any fix needs to be consistent with the epoch-millisecond sync timestamp convention used across the sync API.
Related: existing sync defects where records are dropped or skipped are tracked separately and should not be folded into this work.