> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laportenard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Conflict resolution

> Version tracking, reconciliation strategies, merge logic, and conflict prevention.

## How conflicts happen

Even with leases, version conflicts can occur:

* A terminal sends `ORDER_SNAPSHOT { baseVersion: 3 }` but the hub already has version 4
* A terminal reconnects after a network drop and sends a stale snapshot
* Two terminals briefly hold overlapping leases during the disconnect grace period

## Version tracking

Every order in the hub has an auto-incrementing **version** number:

```sql theme={null}
-- orderStore.upsert() increments version on each write
UPDATE orders SET version = version + 1, snapshot = ?, updated_at = datetime('now')
WHERE pos_reference = ?
```

When a terminal sends `ORDER_SNAPSHOT { baseVersion }`:

1. Hub compares `baseVersion` against the stored version
2. If `baseVersion >= storedVersion`: accept, increment version, broadcast
3. If `baseVersion < storedVersion`: reject, send `CONFLICT { hubVersion, hubSnapshot }`

## Hub-side conflict detection

In `nu_pos_hub/src/handlers/orderHandler.ts`:

```
Terminal sends ORDER_SNAPSHOT { posReference: "ref-1", baseVersion: 2, snapshot }

Hub checks:
  1. Does terminal hold lease for "ref-1"?  -> No: send LEASE_DENIED
  2. Is baseVersion >= stored version?       -> No: send CONFLICT
  3. Accept: upsert (version = stored + 1), broadcast ORDER_UPDATED
```

The hub always has the authoritative version. Terminals must resolve conflicts before retrying.

## Frontend reconciliation

When the terminal receives a `CONFLICT` message, `reconcile()` in `nu_pos_react/src/realtime/sync/reconcile.ts` decides what to do.

### Strategies

| Strategy        | When used                                      | Action                                        |
| --------------- | ---------------------------------------------- | --------------------------------------------- |
| `accept_remote` | No local changes, paid orders, far behind      | Replace local state with hub snapshot         |
| `merge`         | Local has new line additions, 1 version behind | Append local-only lines to hub snapshot       |
| `keep_local`    | (Reserved for future use)                      | Re-send local version (requires version bump) |

### Decision flow

```
CONFLICT received
    |
    +-- No local line changes?      --> accept_remote
    |
    +-- Order is paid?              --> accept_remote
    |
    +-- More than 1 version behind? --> accept_remote
    |
    +-- Local has new lines not in remote?
    |       |
    |       +-- Yes: merge (remote lines + local-only additions)
    |       +-- No:  accept_remote
```

### Merge logic

When a merge is possible (terminal is exactly 1 version behind with local-only line additions):

<Steps>
  <Step title="Build remote set">
    Build a set of remote line IDs
  </Step>

  <Step title="Find local-only lines">
    Find local lines whose IDs are not in the remote set (these are new additions)
  </Step>

  <Step title="Concatenate">
    `remote.lines + localOnlyLines`
  </Step>

  <Step title="Recalculate totals">
    `remote.totals + sum(localOnlyLines)`
  </Step>
</Steps>

This handles the common case of two terminals adding items to the same order concurrently.

### Example

```
Hub state (v3):   lines = [A, B, C]
Local state (v2): lines = [A, B, D]    (terminal added D locally)

CONFLICT: baseVersion=2, hubVersion=3

Merge result:     lines = [A, B, C, D]  (hub's C + local's D)
```

## UI integration

When a conflict occurs, the `SyncUIProvider` shows a `ConflictDialog`:

* **"Load Latest"** — Calls `reconcile()` with `accept_remote`, replaces local order state
* **"Keep Mine"** — User decides to discard the remote and try to re-send (rare)

The dialog shows the order reference, hub version number, and number of lines in the hub version.

## Conflict prevention

The best conflict resolution is prevention. The system minimizes conflicts through:

1. **Leases** — Only the lease holder can submit snapshots
2. **Heartbeats** — Keep leases alive during active editing
3. **Optimistic versioning** — Send `baseVersion` with every snapshot so the hub can detect staleness
4. **Instant broadcast** — Other terminals see changes in real-time, reducing the window for stale edits
