# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Alta Video Camera Proxy — an Electron desktop app that authenticates with Avigilon Alta Video deployments, discovers cameras, and launches external proxy executables (`aware-cam-proxy-win.exe`, `aware-cam-proxy.exe`) to establish camera connections. Windows-only due to the proxy executables. ## Commands ```bash npm start # Run the app npm run dev # Run with DevTools open (--dev flag) npm run build # Build portable Windows .exe (output: dist/) npm run build-test # Build to directory without packaging ``` No test framework is configured. No linter is configured. ## Architecture This is a vanilla Electron app (no React/Vue/framework). Four files form the entire application: ``` main.js → Electron main process: IPC handlers, API calls (axios), profile CRUD, camera proxy process spawning, password encryption (CryptoJS + machine-derived key) preload.js → contextBridge exposing window.electronAPI with typed IPC invoke wrappers renderer.js → All UI logic: DOM manipulation, state management, event handlers index.html → Static HTML shell, no inline scripts (CSP enforced) styles.css → Dark theme using CSS custom properties ``` ### IPC Communication Pattern All cross-process communication follows one pattern: 1. `main.js` registers handler: `ipcMain.handle('channel-name', async (event, params) => { ... })` 2. `preload.js` exposes it: `channelName: (params) => ipcRenderer.invoke('channel-name', params)` 3. `renderer.js` calls it: `const result = await window.electronAPI.channelName(params)` All handlers return `{ success: boolean, message?: string, ...data }`. ### IPC Channels | Channel | Purpose | |---------|---------| | `api-login` | POST /api/v1/dologin, returns cookies | | `api-get-devices` | GET /api/v1/devices with cookie auth | | `api-get-auth-info` | GET /api/v1/auth to verify session | | `profiles-load/save/get/delete/update` | CRUD for `~/.alta-api-profiles.json` | | `camera-proxy-launch` | Spawns aware-cam-proxy-win.exe (user/pass method) | | `camera-proxy-cookie-launch` | Spawns aware-cam-proxy.exe (cookie method) | | `camera-proxy-stop` | Kills all proxy processes via taskkill/powershell | | `camera-proxy-check` | Checks if proxy executable exists | | `camera-proxy-version` | Runs proxy with -v flag | ### State Management (renderer.js) All connection state lives in the `sessionData` object (deploymentUrl, cookies, isConnected). There is no separate `isConnected` flag — always use `sessionData.isConnected`. Active proxy processes are tracked in two Maps: `activeProxyConnections` and `activeCookieProxyConnections`, keyed by device GUID. Max 2 simultaneous connections (`MAX_PROXY_CONNECTIONS`). ### Security Model - Context isolation enabled, nodeIntegration disabled - CSP meta tag: `script-src 'self'` — no inline scripts or onclick handlers allowed - Batch file inputs are sanitized via `sanitizeBatchInput()` to prevent command injection - Encryption key derived from machine identifiers (hostname, homedir, username) via SHA-256 - Legacy profiles auto-migrate from old static key on first load - Clipboard is cleared 30 seconds after password copy - Passwords never written to DOM; kept only in JS variables (`selectedProfile`) ### Profile Storage Profiles stored at `~/.alta-api-profiles.json`. Passwords encrypted with CryptoJS AES using a machine-derived key. The `profiles-load` handler strips passwords before sending to renderer; `profiles-get` decrypts for a specific profile when needed. ## Key Conventions - No inline event handlers in HTML — all use `addEventListener` in renderer.js - All user-provided content rendered to DOM must go through `escapeHtml()` (XSS prevention) - External processes spawned with `detached: true` + `unref()` so they survive if the app closes - Device list filters out cloud cameras (`capabilities.localStorage === false` only) - `clearDeviceList()` must NOT clear proxy connection Maps (proxies may still be running) ## External Executables - `aware-cam-proxy-win.exe` — username/password auth proxy (required) - `aware-cam-proxy.exe` — cookie-based auth proxy (optional) These are not bundled via npm. They must be in the app root directory.