> ## 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.

# Architecture

> System topology, component overview, and data flow for the sync system.

## System topology

```
  ┌─────────────┐  WebSocket  ┌───────────────────────────────────────────┐
  │ Terminal 1  │◄───────────►│              POS Sync Hub                 │
  │  (Browser)  │             │             (Raspberry Pi)                │
  └─────────────┘             │                                           │
                              │  ┌─────────────────┐  ┌───────────────┐  │
  ┌─────────────┐  WebSocket  │  │  Lease Manager  │  │  Order Store  │  │
  │ Terminal 2  │◄───────────►│  └─────────────────┘  └───────────────┘  │
  │  (Browser)  │             │                                           │
  └─────────────┘             │  ┌─────────────────┐  ┌───────────────┐  │
        ⋮                     │  │   Event Log     │  │  Table Store  │  │
  ┌─────────────┐  WebSocket  │  └─────────────────┘  └───────────────┘  │
  │ Terminal N  │◄───────────►│                                           │
  │  (Browser)  │             │  ┌─────────────────────────────────────┐  │
  └─────────────┘             │  │          SQLite (WAL mode)          │  │
                              │  └─────────────────────────────────────┘  │
                              └──────────────────────┬────────────────────┘
                                                     │ HTTP POST
                                                     │ (Forwarder, 5s cycle)
                                                     ▼
                              ┌───────────────────────────────────────────┐
                              │               Odoo Cloud                  │
                              │                                           │
                              │  POST /pos-api/v1/orders/{create,update}  │
                              │  POST /web/session/authenticate           │
                              │                                           │
                              │  ┌──────────────┐  ┌──────────────────┐  │
                              │  │  pos.order   │  │   order_audit    │  │
                              │  └──────────────┘  └──────────────────┘  │
                              └───────────────────────────────────────────┘
```

## Three-tier data flow

### 1. Terminal (browser)

The POS frontend connects to the hub via WebSocket. On every order change, the terminal sends an `ORDER_SNAPSHOT` message containing the full order state. It does not talk to Odoo directly in hub mode.

**Key modules** (in `nu_pos_react/src/realtime/`):

* `hubTransport.ts` — Implements `SyncTransport` for hub mode
* `hub/hubConnection.ts` — WebSocket lifecycle with auto-reconnect
* `hub/hubDiscovery.ts` — Resolves hub URL from bootstrap config

### 2. Hub (Raspberry Pi)

The hub is a stateless-except-SQLite Node.js service that:

1. Authenticates terminals via Odoo session validation
2. Enforces single-writer order ownership through [leases](/sync/leasing)
3. Persists order snapshots with optimistic versioning
4. Broadcasts changes to all other connected terminals
5. Forwards events to Odoo in the background

**Key modules** (in `nu_pos_hub/src/`):

* `handlers/` — Message handlers (auth, lease, order, table)
* `storage/` — SQLite stores (orders, leases, events, tables)
* `leasing/leaseManager.ts` — Lease business logic
* `upstream/forwarder.ts` — Background event drain to Odoo

### 3. Odoo (cloud)

Odoo is the system of record. The hub forwards order events via the existing `/pos-react/api/orders/{create,update}` endpoints. These are idempotent by `pos_reference`, so re-forwarding is safe.

## Direct mode vs hub mode

| Aspect                 | Direct mode                | Hub mode                             |
| ---------------------- | -------------------------- | ------------------------------------ |
| Connection             | HTTP polling (2s interval) | WebSocket (real-time)                |
| Conflict prevention    | Local tab locks only       | Distributed leases via hub           |
| Cross-terminal updates | Poll-based (2-15s delay)   | Instant broadcast                    |
| Offline support        | localStorage outbox        | localStorage outbox + hub reconnect  |
| Infrastructure         | None (just Odoo)           | Raspberry Pi running hub             |
| Odoo calls             | Each terminal calls Odoo   | Hub is sole Odoo gateway             |
| Activation             | Default                    | Odoo config: `nu_hub_enabled = True` |

Both modes implement the same `SyncTransport` interface (see [transport layer](/sync/transport-layer)), so the UI code is identical regardless of mode.

## Component ownership

```
  ┌─────────────────────────────────────────────────────────────────────┐
  │  nu_pos_sync_protocol/   Shared types, validators, constants        │
  └───────────────────────────────────┬─────────────────────────────────┘
                                      │
                   ┌──────────────────┴──────────────────┐
                   │                                     │
                   ▼                                     ▼
  ┌────────────────────────┐        ┌────────────────────────────────────┐
  │      nu_pos_hub/       │        │          nu_pos_react/             │
  │  Consumes @nu/sync-    │        │  Mirrors types in transport.ts     │
  │  protocol for WS       │        │  (no direct npm dependency)        │
  │  message handling      │        │                                    │
  └────────────────────────┘        └────────────────────────────────────┘
```

<Info>
  The frontend does not import `@nu/sync-protocol` directly. Instead, `transport.ts` defines `OrderSnapshotData` (a mirror of the protocol's `OrderSnapshot`) to avoid coupling the browser bundle to the Node.js protocol package.
</Info>
