Files
peji f57183448f Update CLAUDE.md and README.md for cookie-only architecture
Rewrite both docs to reflect the current state: Chrome extension
cookie auth, no profiles/passwords, simplified IPC channels and
file structure, updated troubleshooting and security sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:30:11 -05:00

5.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Alta Proxy Tool (APT) — an Electron desktop app that authenticates with Avigilon Alta Video deployments via a companion Chrome extension, discovers cameras, and launches aware-cam-proxy.exe to establish camera connections. Authentication uses cookie import from Chrome — no username/password login flow. Windows-only due to the proxy executable.

Repository

Commands

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). Core files:

main.js      → Electron main process: IPC handlers, API calls (axios),
                cookie proxy process spawning, local HTTP cookie server
preload.js   → contextBridge exposing window.electronAPI with IPC 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

A companion Chrome extension lives in chrome-extension/:

chrome-extension/
  manifest.json  → Manifest V3, cookies + activeTab permissions
  popup.html     → Extension popup UI
  popup.css      → Dark theme matching the Electron app
  popup.js       → Tab detection, cookie retrieval, POST to localhost
  icon*.png      → Placeholder icons

Authentication Flow

There is no login form or profile system. Authentication works exclusively through the Chrome extension cookie bridge:

  1. User logs into Alta deployment in Chrome
  2. Clicks the Chrome extension popup → "Send Cookie to APT"
  3. Extension POSTs {deploymentUrl, cookieValue} to http://127.0.0.1:18247/cookie with X-APT-Token header
  4. main.js HTTP server validates and forwards via IPC push to renderer
  5. renderer.js handleExtensionCookie() sets session state, auto-populates cookie key, fetches devices

The extension is loaded unpacked via chrome://extensions/ → Developer mode → Load unpacked → select chrome-extension/.

IPC Communication Pattern

Most cross-process communication follows the request/response 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 }.

There is one push-pattern channel for the Chrome extension cookie bridge:

  • main.js sends: mainWindow.webContents.send('extension-cookie-received', data)
  • preload.js bridges: ipcRenderer.on('extension-cookie-received', callback)
  • renderer.js listens via window.electronAPI.onExtensionCookie(callback)

IPC Channels

Channel Purpose
api-get-devices GET /api/v1/devices with cookie auth
api-get-auth-info GET /api/v1/auth to verify session
camera-proxy-cookie-launch Spawns aware-cam-proxy.exe (cookie method)
camera-proxy-stop Kills all proxy processes via taskkill/powershell
extension-cookie-received Push channel: cookie data from Chrome extension → renderer

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 cookie proxy processes are tracked in activeCookieProxyConnections Map, keyed by device GUID.

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
  • Local HTTP cookie server (port 18247) bound to 127.0.0.1 only
  • Cookie server validates: shared token header, CORS restricted to chrome-extension:// origins, deployment URL must be *.avasecurity.com or *.avigilon.com over HTTPS, type/length limits on all inputs, 64KB body size limit

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 Executable

  • aware-cam-proxy.exe — cookie-based auth proxy (required)

Not bundled via npm. Must be in the app root directory. Gitignored along with *.pdf, node_modules/, and dist/.