# Architecture

## Process Model

ImEX RPS has two main runtimes:

- Electron main process: window lifecycle, native menus, file system access, estimate decoding, file watching/scanning, audit file dialogs, updater, app-level settings, analytics, and IPC.
- React renderer process: UI, routing, Redux state, Apollo GraphQL operations, Firebase auth, and renderer-side IPC listeners.

The renderer does not get Node integration. The preload script exposes a controlled bridge:

- `window.ipcRenderer.send(channel, data)`
- `window.ipcRenderer.on(channel, handler)`
- `window.ipcRenderer.invoke(channel, data)`
- `window.ipcRenderer.removeAllListeners(...)`
- `window.logger.*`

## Entrypoints

Electron:

- `electron/main.js` decides whether to run the source main file or bundled `dist-electron/main.cjs`.
- `electron/main-src.js` is the main source file.
- `electron/preload.js` decides whether to run the source preload or bundled `dist-electron/preload.cjs`.
- `electron/preload-src.js` exposes IPC/logger bridges.
- `scripts/build-electron.mjs` bundles main/preload outputs.

Renderer:

- `src/index.jsx` initializes Sentry renderer, Redux Provider, `MemoryRouter`, `PersistGate`, and `<App />`.
- `src/App/App.jsx` initializes Apollo, AntD context/theme, auth session check, IPC side effects, and authorized/unauthorized routing.
- `src/components/pages/routes/routes.page.jsx` renders the main app shell and routes.

## Routing

Routes are memory-router routes because this is an Electron app:

- `/` Jobs
- `/settings` Settings
- `/reporting` Reporting
- `/audit` Audit
- `/scan` Scan
- `/admin` Admin

The app shell includes the side menu, notifications modal, release notes, and update manager.

## Redux Shape

Store setup:

- `src/redux/store.js`
- Redux core `legacy_createStore`
- Saga middleware
- Redux logger in development
- Redux DevTools compose if present
- redux-persist wrapper with all active reducers currently blacklisted

Reducers:

- `application`: watcher status, watched paths, selected job id, selected target percent, settings, update state, release notes, estimate scrubber results.
- `user`: current user, bodyshop, targets, fingerprint, auth errors, notifications, dark mode.
- `reporting`: report date range, report rows, scorecard, audit data/errors/loading, excluded ids, cached jobs.
- `scan`: scan loading state, last scanned, estimate list.

Sagas:

- `applicationSagas`
- `userSagas`
- `reportingSagas`
- `scanSagas`

## Data Flow for Estimate Import

1. User configures `filePaths` in settings.
2. Electron store persists those paths.
3. `electron/file-watcher/file-watcher.js` watches paths with chokidar.
4. New/changed estimate files are decoded by `electron/decoder/decoder.js`.
5. Main process sends decoded payloads over IPC.
6. Renderer `src/ipc/ipc-renderer-handler.js` receives decoded estimates.
7. Renderer GraphQL helper `UpsertEstimate` writes jobs/joblines to Hasura.
8. Jobs UI queries data back through Apollo.

## Data Flow for Job Details

1. A list item dispatches selected job id to Redux `application`.
2. `jobs-detail.organism.jsx` debounces selected id briefly to avoid rendering a stale/partial left panel.
3. Apollo queries `QUERY_JOB_BY_PK`.
4. Detail subcomponents render job metadata, joblines, targets, group controls, claims clerk, estimate scrubber, and other actions.

## IPC Contract

IPC channel names live in `src/ipc.types.json`, imported by:

- `src/ipc.types.js` for ESM renderer code.
- `src/ipc.types.commonjs.js` for CommonJS Electron code.

When adding IPC:

- Add channel names to `src/ipc.types.json`.
- Register main handlers in the relevant Electron module.
- Register renderer listeners in `src/ipc/ipc-renderer-handler.js` or a local component effect.
- Keep handlers idempotent when possible; repeated imports/listeners can create duplicate events.

