'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const { PassThrough } = require('node:stream'); const { AppRuntime, PairingController, createBridgeHandler, loadPairingEnvelope, } = require('../src/electron-runtime'); const { APT_EXTENSION_ORIGIN, BridgeAuth, computeCookieProof, createRequestLimiter, } = require('../src/bridge-auth'); const { createSessionStore } = require('../src/session-store'); const ROOT = path.join(__dirname, '..'); const read = (name) => fs.readFileSync(path.join(ROOT, name), 'utf8'); function responseHarness() { return { statusCode: 0, headers: {}, body: '', setHeader(name, value) { this.headers[name.toLowerCase()] = value; }, writeHead(statusCode, headers = {}) { this.statusCode = statusCode; for (const [name, value] of Object.entries(headers)) this.setHeader(name, value); }, end(chunk = '') { this.body += chunk; }, }; } function requestHarness({ method = 'POST', origin = APT_EXTENSION_ORIGIN, url = '/cookie', body = '{}' } = {}) { const request = new PassThrough(); request.method = method; request.url = url; request.headers = { origin }; process.nextTick(() => request.end(body)); return request; } test('runtime keeps Alta credentials in main-owned modules and exposes only non-secret state', async () => { const sessionStore = createSessionStore(); sessionStore.establish('https://customer.avasecurity.com', 'top-secret-cookie'); const calls = []; const tracked = []; const proxyManager = { launchProxy(request) { calls.push(request); tracked.push({ processId: 91, deviceId: request.deviceId, status: 'running', startedAt: 1 }); return { success: true, processId: 91, deviceId: request.deviceId, status: 'running' }; }, stopProxy(processId) { calls.push({ processId }); tracked.splice(0, tracked.length); return { success: true, processId, status: 'stop-requested' }; }, listTrackedProxies() { return tracked.slice(); }, }; const runtime = new AppRuntime({ sessionStore, altaClient: { getDevices: async () => [{ guid: '550e8400-e29b-41d4-a716-446655440000' }], getDeviceSites: async () => [], getAuthInfo: async () => ({ user: 'safe' }), }, proxyManager, checkForUpdate: async ({ currentVersion }) => ({ status: 'up-to-date', currentVersion }), currentVersion: '1.0.0', openExternal: async () => {}, }); assert.deepEqual(await runtime.getDevices(), { success: true, devices: [{ id: '550e8400-e29b-41d4-a716-446655440000', name: null, type: null, model: null, address: null, siteId: null, deviceGroupId: null, displayStatus: null, localStorage: null, }], }); const launched = await runtime.launchProxy('550e8400-e29b-41d4-a716-446655440000'); assert.equal(launched.success, true); assert.deepEqual(calls[0], { deploymentHost: 'customer.avasecurity.com', cookie: 'top-secret-cookie', deviceId: '550e8400-e29b-41d4-a716-446655440000', }); assert.deepEqual(runtime.getConnectionState(), { connected: true, origin: 'https://customer.avasecurity.com', activeProxies: [{ deviceId: '550e8400-e29b-41d4-a716-446655440000', processId: 91 }], }); assert.equal(JSON.stringify(launched).includes('top-secret-cookie'), false); assert.equal(JSON.stringify(runtime.getConnectionState()).includes('top-secret-cookie'), false); assert.equal((await runtime.stopProxy('550e8400-e29b-41d4-a716-446655440000')).success, true); assert.deepEqual(calls[1], { processId: 91 }); assert.equal((await runtime.stopProxy(999)).success, false); }); test('runtime discovers and projects hierarchy while metadata failures preserve cameras', async () => { const deviceId = '550e8400-e29b-41d4-a716-446655440000'; const runtime = new AppRuntime({ sessionStore: createSessionStore(), altaClient: { getDevices: async () => [{ guid: deviceId, name: 'Camera', server_group_id: 'site-1', secret: 'drop-me', }], getDeviceSites: async () => { throw Object.assign(new Error('tenant secret'), { code: 'ALTA_HTTP_ERROR' }); }, getDeviceGroups: async () => [{ id: 'group-1', name: 'Lobby', parent_id: null }], }, proxyManager: { listTrackedProxies: () => [] }, }); const result = await runtime.getDeviceHierarchy(); assert.equal(result.success, true); assert.deepEqual(result.hierarchy.devices.map(({ id }) => id), [deviceId]); assert.deepEqual(result.hierarchy.sites, []); assert.deepEqual(result.hierarchy.groups, [{ id: 'group-1', name: 'Lobby', parentId: null, pendingDeletionStart: null, }]); assert.equal(result.hierarchy.diagnostics.sites.error, 'Device sites unavailable'); assert.doesNotMatch(JSON.stringify(result), /drop-me|tenant secret/); }); test('runtime enforces a bounded whole-discovery deadline', async () => { const runtime = new AppRuntime({ sessionStore: createSessionStore(), altaClient: { getDevices: async () => new Promise(() => {}), getDeviceSites: async () => [], getDeviceGroups: async () => [], }, proxyManager: { listTrackedProxies: () => [] }, discoveryTimeoutMs: 25, }); const result = await runtime.getDeviceHierarchy(); assert.deepEqual(result, { success: false, hierarchy: { devices: [], sites: [], groups: [] }, message: 'Alta device discovery timed out', }); }); test('newest hierarchy discovery owns the launch allowlist when completions arrive out of order', async () => { const sessionStore = createSessionStore(); sessionStore.establish('https://customer.avasecurity.com', 'synthetic-cookie'); const deviceA = '550e8400-e29b-41d4-a716-44665544000a'; const deviceB = '550e8400-e29b-41d4-a716-44665544000b'; const pending = []; const launches = []; const runtime = new AppRuntime({ sessionStore, altaClient: { getDevices: () => new Promise((resolve) => pending.push(resolve)), getDeviceSites: async () => [], getDeviceGroups: async () => [], }, proxyManager: { launchProxy(request) { launches.push(request.deviceId); return { processId: 5000 + launches.length, deviceId: request.deviceId, status: 'running' }; }, listTrackedProxies: () => [], }, }); const staleA = runtime.getDeviceHierarchy(); const freshB = runtime.getDeviceHierarchy(); pending[1]([{ guid: deviceB }]); assert.equal((await freshB).success, true); assert.equal((await runtime.launchProxy(deviceB)).success, true); pending[0]([{ guid: deviceA }]); assert.deepEqual(await staleA, { success: false, stale: true, hierarchy: { devices: [], sites: [], groups: [] }, message: 'Alta device discovery result is stale', }); assert.equal((await runtime.launchProxy(deviceA)).success, false); assert.deepEqual(launches, [deviceB]); }); test('disconnect and session changes invalidate pending discovery without repopulating the allowlist', async () => { const deviceId = '550e8400-e29b-41d4-a716-44665544000c'; for (const invalidate of ['disconnect', 'session-change']) { const sessionStore = createSessionStore(); sessionStore.establish('https://first.avasecurity.com', 'synthetic-cookie'); let resolveDevices; const runtime = new AppRuntime({ sessionStore, altaClient: { getDevices: () => new Promise((resolve) => { resolveDevices = resolve; }), getDeviceSites: async () => [], getDeviceGroups: async () => [], }, proxyManager: { listTrackedProxies: () => [] }, }); const discovery = runtime.getDeviceHierarchy(); if (invalidate === 'disconnect') { assert.equal((await runtime.disconnect()).success, true); } else { sessionStore.establish('https://second.avasecurity.com', 'replacement-cookie'); runtime.onSessionChanged(); } resolveDevices([{ guid: deviceId }]); assert.equal((await discovery).stale, true, invalidate); assert.equal(runtime.allowedDeviceIds.size, 0, invalidate); } }); test('launch allowlist remains bound to the session origin that produced it', async () => { const deviceId = '550e8400-e29b-41d4-a716-44665544000d'; const sessionStore = createSessionStore(); sessionStore.establish('https://first.avasecurity.com', 'synthetic-cookie'); let launches = 0; const runtime = new AppRuntime({ sessionStore, altaClient: { getDevices: async () => [{ guid: deviceId }], getDeviceSites: async () => [], getDeviceGroups: async () => [], }, proxyManager: { listTrackedProxies: () => [], launchProxy() { launches += 1; }, }, }); assert.equal((await runtime.getDeviceHierarchy()).success, true); sessionStore.establish('https://second.avasecurity.com', 'replacement-cookie'); assert.equal((await runtime.launchProxy(deviceId)).success, false); assert.equal(launches, 0); }); test('runtime rejects discovery deadlines above 60 seconds', () => { assert.throws(() => new AppRuntime({ discoveryTimeoutMs: 60_001 }), /discovery timeout/i); }); test('bridge authenticates itself before accepting a one-time HMAC cookie request', async () => { const protect = (value) => Buffer.from(`protected:${value}`); const unprotect = (value) => Buffer.from(value).toString().slice('protected:'.length); const auth = new BridgeAuth({ protect, unprotect }); const secret = auth.rotate().secret; const sessionStore = createSessionStore(); let stateNotifications = 0; const handler = createBridgeHandler({ bridgeAuth: auth, sessionStore, onConnectionStateChanged: () => { stateNotifications += 1; }, }); const unknownPreflight = requestHarness({ method: 'OPTIONS', origin: 'chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }); const unknownResponse = responseHarness(); await handler(unknownPreflight, unknownResponse); assert.equal(unknownResponse.statusCode, 403); assert.equal(unknownResponse.headers['access-control-allow-origin'], undefined); const allowedPreflight = requestHarness({ method: 'OPTIONS' }); const allowedResponse = responseHarness(); await handler(allowedPreflight, allowedResponse); assert.equal(allowedResponse.statusCode, 204); assert.equal(allowedResponse.headers['access-control-allow-origin'], APT_EXTENSION_ORIGIN); assert.doesNotMatch(allowedResponse.headers['access-control-allow-headers'], /X-APT-Pairing/i); const clientNonce = Buffer.alloc(32, 3).toString('base64url'); const challengeResponse = responseHarness(); await handler(requestHarness({ url: '/challenge', body: JSON.stringify({ clientNonce }) }), challengeResponse); assert.equal(challengeResponse.statusCode, 200); const challenge = JSON.parse(challengeResponse.body); assert.equal(JSON.stringify(challenge).includes(secret), false); const cookieBody = { clientNonce, serverNonce: challenge.serverNonce, deploymentUrl: 'https://customer.avasecurity.com', cookieValue: 'valid-cookie', }; cookieBody.proof = computeCookieProof(secret, cookieBody); const acceptedResponse = responseHarness(); await handler(requestHarness({ body: JSON.stringify(cookieBody) }), acceptedResponse); assert.equal(acceptedResponse.statusCode, 200); assert.deepEqual(sessionStore.describe(), { connected: true, origin: 'https://customer.avasecurity.com' }); assert.equal(stateNotifications, 1); assert.equal(acceptedResponse.body.includes('valid-cookie'), false); const replayResponse = responseHarness(); await handler(requestHarness({ body: JSON.stringify(cookieBody) }), replayResponse); assert.equal(replayResponse.statusCode, 403); }); test('bridge limiter encloses body reads and HMAC authentication under forged floods', async () => { const auth = new BridgeAuth({ protect: (value) => Buffer.from(value), unprotect: (value) => Buffer.from(value).toString() }); auth.rotate(); const limiter = createRequestLimiter({ maxConcurrent: 1 }); const handler = createBridgeHandler({ bridgeAuth: auth, sessionStore: createSessionStore(), limiter, deadlineMs: 50 }); const held = new PassThrough(); held.method = 'POST'; held.url = '/challenge'; held.headers = { origin: APT_EXTENSION_ORIGIN }; const first = handler(held, responseHarness()); await new Promise((resolve) => setImmediate(resolve)); assert.equal(limiter.active, 1); const rejected = responseHarness(); await handler(requestHarness({ url: '/challenge', body: JSON.stringify({ clientNonce: 'A'.repeat(43) }) }), rejected); assert.equal(rejected.statusCode, 429); held.end('{}'); await first; }); test('pairing envelope persists encrypted with restrictive permissions and secrets are returned once', () => { const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'apt-pairing-')); const envelopePath = path.join(directory, 'bridge-pairing.json'); const protect = (value) => Buffer.from(`dpapi:${value}`); const unprotect = (value) => Buffer.from(value).toString().slice('dpapi:'.length); const controller = new PairingController({ envelopePath, protect, unprotect }); const first = controller.initialize(); assert.equal(first.paired, true); assert.match(first.secret, /^[A-Za-z0-9_-]{43}$/); assert.deepEqual(controller.getStatus(), { paired: true }); const persisted = loadPairingEnvelope(envelopePath, { protect, unprotect }); assert.equal(Object.values(persisted).includes(first.secret), false); assert.equal(fs.readFileSync(envelopePath, 'utf8').includes(first.secret), false); if (process.platform !== 'win32') assert.equal(fs.statSync(envelopePath).mode & 0o777, 0o600); const rotated = controller.rotate(); assert.match(rotated.secret, /^[A-Za-z0-9_-]{43}$/); assert.notEqual(rotated.secret, first.secret); assert.deepEqual(controller.getStatus(), { paired: true }); controller.revoke(); assert.deepEqual(controller.getStatus(), { paired: false }); assert.equal(fs.existsSync(envelopePath), false); }); test('pairing fails closed and reports unavailable without secure storage', () => { const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'apt-pairing-unavailable-')); const controller = new PairingController({ envelopePath: path.join(directory, 'bridge-pairing.json') }); assert.deepEqual(controller.initialize(), { paired: false, unavailable: true }); assert.deepEqual(controller.getStatus(), { paired: false, unavailable: true }); assert.throws(() => controller.rotate(), (error) => error.code === 'SECURE_STORAGE_UNAVAILABLE'); }); test('runtime reconciles exited children and permits relaunch for the same device', async () => { const sessionStore = createSessionStore(); sessionStore.establish('https://customer.avasecurity.com', 'synthetic-cookie'); const deviceId = '550e8400-e29b-41d4-a716-446655440000'; const tracked = []; let nextPid = 4101; const runtime = new AppRuntime({ sessionStore, altaClient: { getDevices: async () => [{ guid: deviceId }] }, proxyManager: { launchProxy() { const entry = { processId: nextPid++, deviceId, status: 'running', startedAt: 1 }; tracked.push(entry); return { success: true, ...entry }; }, stopProxy() { throw new Error('unused'); }, listTrackedProxies() { return tracked.slice(); }, }, }); await runtime.getDevices(); assert.equal((await runtime.launchProxy(deviceId)).processId, 4101); tracked.length = 0; assert.deepEqual(runtime.getConnectionState().activeProxies, []); assert.equal((await runtime.launchProxy(deviceId)).processId, 4102); }); test('disconnect stops every owned proxy before clearing the Alta session', async () => { const sessionStore = createSessionStore(); sessionStore.establish('https://customer.avasecurity.com', 'synthetic-cookie'); const tracked = [ { processId: 4101, deviceId: '550e8400-e29b-41d4-a716-446655440000', status: 'running', startedAt: 1 }, { processId: 4102, deviceId: '550e8400-e29b-41d4-a716-446655440001', status: 'running', startedAt: 1 }, ]; const stopped = []; const runtime = new AppRuntime({ sessionStore, altaClient: {}, proxyManager: { listTrackedProxies() { return tracked.slice(); }, stopProxy(processId) { stopped.push(processId); tracked.splice(tracked.findIndex((entry) => entry.processId === processId), 1); return { success: true, processId, status: 'stop-requested' }; }, }, }); const state = await runtime.disconnect(); assert.deepEqual(stopped, [4101, 4102]); assert.equal(state.connected, false); assert.deepEqual(state.activeProxies, []); }); test('disconnect reports failure truthfully and retains session when an owned proxy cannot stop', async () => { const sessionStore = createSessionStore(); sessionStore.establish('https://customer.avasecurity.com', 'synthetic-cookie'); const tracked = [{ processId: 4101, deviceId: '550e8400-e29b-41d4-a716-446655440000', status: 'running', startedAt: 1 }]; const runtime = new AppRuntime({ sessionStore, altaClient: {}, proxyManager: { listTrackedProxies() { return tracked.slice(); }, stopProxy() { return { success: false, processId: 4101, status: 'permission-denied' }; }, }, }); const state = await runtime.disconnect(); assert.equal(state.success, false); assert.equal(state.connected, true); assert.deepEqual(state.activeProxies.map((entry) => entry.processId), [4101]); }); test('kill request without exit keeps proxy tracked and session connected until confirmed exit', async () => { const { EventEmitter } = require('node:events'); const { createProxyManager } = require('../src/proxy-launch'); const sessionStore = createSessionStore(); sessionStore.establish('https://customer.avasecurity.com', 'synthetic-cookie'); const deviceId = '550e8400-e29b-41d4-a716-446655440000'; const child = new EventEmitter(); child.pid = 4101; child.exitCode = null; child.signalCode = null; child.kill = () => true; let timeoutCallback; const proxyManager = createProxyManager({ appDirectory: 'C:\\Program Files\\Alta Proxy Tool', fs: { existsSync: () => true }, spawn: () => child, platform: 'win32', stopTimeoutMs: 10, setTimeout(callback) { timeoutCallback = callback; return 1; }, clearTimeout() {}, }); proxyManager.launchProxy({ deploymentHost: 'customer.avasecurity.com', cookie: 'synthetic-cookie', deviceId }); const runtime = new AppRuntime({ sessionStore, altaClient: {}, proxyManager }); const firstDisconnect = runtime.disconnect(); assert.equal(proxyManager.listTrackedProxies()[0].status, 'stopping'); timeoutCallback(); const failed = await firstDisconnect; assert.equal(failed.success, false); assert.equal(failed.connected, true); assert.deepEqual(failed.activeProxies, [{ deviceId, processId: 4101 }]); child.exitCode = 0; child.emit('exit', 0, null); const disconnected = await runtime.disconnect(); assert.equal(disconnected.success, true); assert.equal(disconnected.connected, false); assert.deepEqual(disconnected.activeProxies, []); }); test('update runtime is check-only and opens only the fixed GitPeji releases page', async () => { const opened = []; const runtime = new AppRuntime({ sessionStore: createSessionStore(), altaClient: {}, proxyManager: {}, checkForUpdate: async ({ currentVersion }) => ({ status: 'update-available', currentVersion, latestVersion: '1.1.0' }), currentVersion: '1.0.0', openExternal: async (url) => { opened.push(url); }, }); assert.deepEqual(await runtime.checkForUpdates(), { success: true, status: 'update-available', currentVersion: '1.0.0', latestVersion: '1.1.0', }); assert.deepEqual(await runtime.openFixedReleasesPage(), { success: true }); assert.deepEqual(opened, ['https://git.pejicorp.com/peji/Alta-Proxy-Tool/releases']); }); test('preload and renderer expose only narrow, credential-free contracts', () => { const preload = read('preload.js'); const renderer = read('renderer.js'); const html = read('index.html'); const expectedMethods = [ 'getDevices', 'getDeviceSites', 'getDeviceGroups', 'getDeviceHierarchy', 'getAuthInfo', 'launchProxy', 'stopProxy', 'disconnect', 'getConnectionState', 'checkForUpdates', 'openFixedReleasesPage', 'rotatePairing', 'revokePairing', 'getPairingStatus', 'onConnectionStateChanged', ]; for (const method of expectedMethods) assert.match(preload, new RegExp(`\\b${method}\\b`)); assert.doesNotMatch(preload, /downloadAndInstall|download-and-install|onUpdateDownloadProgress|onExtensionCookie/); assert.match(preload, /launchProxy:\s*\(deviceId\)/); assert.doesNotMatch(preload, /launchProxy:\s*\([^)]*(?:cookie|origin)/i); assert.doesNotMatch(renderer, /cookieValue|sessionData\.cookies|cookies\s*:/); assert.match(renderer, /state\.connected\s*&&\s*\(!wasConnected\s*\|\|\s*state\.origin\s*!==\s*previousOrigin\)/); assert.match(read('main.js'), /onConnectionStateChanged:\s*\(\)\s*=>\s*\{\s*runtime\.onSessionChanged\(\)/); assert.doesNotMatch(html, /id="cookieKey"|id="altaUsername"|type="password"|updateProgress|Install Update/); assert.match(html, /paired Chrome extension session/i); assert.match(html, /id="pairingSection"[^>]*hidden/); assert.match(html, /id="managePairingBtn"/); assert.match(renderer, /shouldShowPairingOnboarding/); assert.match(renderer, /openFixedReleasesPage/); assert.match(html, /Bridge Pairing/); }); test('Electron quit waits for confirmed cleanup and reports a safe failure instead of disposing', () => { const main = read('main.js'); const beforeQuit = main.slice(main.indexOf("app.on('before-quit'"), main.indexOf("app.on('window-all-closed'")); const preventIndex = beforeQuit.indexOf('event.preventDefault()'); const disconnectIndex = beforeQuit.indexOf('await runtime.disconnect()'); const activeCheckIndex = beforeQuit.indexOf('state.activeProxies.length > 0'); const disposeIndex = beforeQuit.indexOf('runtime.sessionStore.dispose()'); const confirmedQuitIndex = beforeQuit.indexOf('allowConfirmedQuit = true'); const quitIndex = beforeQuit.indexOf('app.quit()'); assert.ok(preventIndex >= 0 && preventIndex < disconnectIndex); assert.ok(disconnectIndex < activeCheckIndex && activeCheckIndex < disposeIndex); assert.ok(disposeIndex < confirmedQuitIndex && confirmedQuitIndex < quitIndex); assert.match(main, /dialog\.showMessageBox/); assert.match(main, /could not confirm that every proxy process exited/i); assert.doesNotMatch(beforeQuit, /taskkill|pkill|wmic/i); }); test('source policy removes legacy credential IPC, shell launch, broad kill, and executable updater', () => { const production = ['main.js', 'preload.js', 'renderer.js', 'index.html', 'src/electron-runtime.js'] .map(read).join('\n'); const forbidden = [ /sanitizeBatchInput/, /taskkill/i, /\.bat\b/i, /download-and-install-update/, /httpsGetFollowRedirects/, /api\.github\.com/i, /github releases/i, /apt-local-bridge-token/, /X-APT-Token/, /cookie-proxy-/, ]; for (const pattern of forbidden) assert.doesNotMatch(production, pattern); assert.doesNotMatch(read('main.js'), /axios/); assert.match(read('main.js'), /event\.sender === webContents/); assert.match(read('main.js'), /frame === webContents\.mainFrame/); assert.match(read('main.js'), /pathToFileURL\(path\.join\(__dirname, 'index\.html'\)\)/); assert.match(read('main.js'), /127\.0\.0\.1/); assert.match(read('main.js'), /18247/); assert.match(read('main.js'), /shell\.openExternal/); }); test('production source and documentation are GitPeji-only with no active GitHub workflow', () => { assert.equal(fs.existsSync(path.join(ROOT, '.github', 'workflows', 'deploy-pages.yml')), false); const sourceAndDocs = [ 'main.js', 'preload.js', 'renderer.js', 'renderer-controller.js', 'index.html', 'src/electron-runtime.js', 'src/proxy-launch.js', 'README.md', 'CLAUDE.md', 'docs/security/2026-08-security-baseline.md', 'docs/plans/2026-08-19-apt-security-foundation.md', ].map(read).join('\n'); assert.doesNotMatch(sourceAndDocs, /github/i); assert.match(sourceAndDocs, /GitPeji/); });