feat: publish Alta Local Camera Discovery

This commit is contained in:
2026-09-01 18:02:14 +00:00
commit 33f28a3d73
30 changed files with 4939 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const path = require('node:path');
const { resolveAppAssetPath } = require('../src/app-protocol');
const staticDir = path.join(__dirname, '..', 'static');
test('app protocol resolves only explicitly packaged renderer assets', () => {
assert.equal(resolveAppAssetPath('app://bundle/index.html', staticDir), path.join(staticDir, 'index.html'));
assert.equal(resolveAppAssetPath('app://bundle/styles.css?v=12', staticDir), path.join(staticDir, 'styles.css'));
assert.equal(resolveAppAssetPath('app://bundle/alta-mark.png', staticDir), path.join(staticDir, 'alta-mark.png'));
assert.equal(resolveAppAssetPath('app://other/index.html', staticDir), null);
assert.equal(resolveAppAssetPath('app://bundle/../main.js', staticDir), null);
assert.equal(resolveAppAssetPath('app://bundle/%2e%2e/main.js', staticDir), null);
assert.equal(resolveAppAssetPath('file:///etc/passwd', staticDir), null);
assert.equal(resolveAppAssetPath('app://bundle/not-packaged.js', staticDir), null);
});
+108
View File
@@ -0,0 +1,108 @@
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const { EventEmitter } = require('node:events');
const {
altaKeyFromName,
cameraFromService,
isLocalAddress,
normalizeResults,
scanCameras,
} = require('../src/discovery');
const validService = (overrides = {}) => ({
name: 'ABH7-C62U-GC3E',
type: 'vaioncam',
protocol: 'tcp',
host: 'avacam-abh7-c62u-gc3e.local.',
addresses: ['fe80::1', '10.0.0.223'],
port: 443,
...overrides,
});
test('extracts an Alta Key from service names', () => {
assert.equal(altaKeyFromName('abh7-c62u-gc3e'), 'ABH7-C62U-GC3E');
assert.equal(altaKeyFromName('ABH7-C62U-GC3E._vaioncam._tcp.local'), 'ABH7-C62U-GC3E');
assert.equal(altaKeyFromName('not-a-key'), null);
});
test('projects a correlated local Bonjour service into a safe camera row', () => {
assert.deepEqual(cameraFromService(validService()), {
alta_key: 'ABH7-C62U-GC3E',
hostname: 'avacam-abh7-c62u-gc3e.local',
web_ui_url: 'https://avacam-abh7-c62u-gc3e.local',
ip_address: '10.0.0.223',
port: 443,
service: '_vaioncam._tcp.local',
});
});
test('rejects uncorrelated or non-local service announcements', () => {
assert.equal(cameraFromService(validService({ type: undefined })), null);
assert.equal(cameraFromService(validService({ protocol: undefined })), null);
assert.equal(cameraFromService(validService({ host: 'avacam-attacker.local.' })), null);
assert.equal(cameraFromService(validService({ port: 8443 })), null);
assert.equal(cameraFromService(validService({ addresses: ['203.0.113.10'] })), null);
assert.equal(cameraFromService(validService({ addresses: [] })), null);
});
test('recognizes supported private and link-local IP scopes', () => {
for (const address of ['10.0.0.1', '172.16.0.1', '172.31.255.254', '192.168.1.1', '169.254.1.1', 'fe80::1', 'fc00::1', 'fd12::1']) {
assert.equal(isLocalAddress(address), true, address);
}
for (const address of ['8.8.8.8', '172.32.0.1', '2001:4860:4860::8888', 'not-an-ip']) {
assert.equal(isLocalAddress(address), false, address);
}
});
test('deduplicates and sorts cameras', () => {
const a = { alta_key: 'AHG2-Z4ND-FVRN', ip_address: '10.0.0.192' };
const b = { alta_key: 'ABH7-C62U-GC3E', ip_address: '10.0.0.223' };
assert.deepEqual(normalizeResults([a, b, a]), [b, a]);
});
test('scans through the Bonjour adapter and closes resources', async () => {
let browserStopped = false;
let bonjourDestroyed = false;
class FakeBonjour {
find(query) {
assert.deepEqual(query, { type: 'vaioncam', protocol: 'tcp' });
const browser = new EventEmitter();
browser.stop = () => { browserStopped = true; };
process.nextTick(() => browser.emit('up', validService()));
return browser;
}
destroy() { bonjourDestroyed = true; }
}
const rows = await scanCameras({ durationMs: 5, BonjourClass: FakeBonjour });
assert.equal(rows.length, 1);
assert.equal(rows[0].alta_key, 'ABH7-C62U-GC3E');
assert.equal(browserStopped, true);
assert.equal(bonjourDestroyed, true);
});
test('caps scan results and closes discovery immediately at the cap', async () => {
let browserStopped = false;
class FakeBonjour {
find() {
const browser = new EventEmitter();
browser.stop = () => { browserStopped = true; };
process.nextTick(() => {
for (let index = 0; index < 10; index += 1) {
const key = `AAAA-BBBB-${String(index).padStart(4, '0')}`;
browser.emit('up', validService({
name: key,
host: `avacam-${key.toLowerCase()}.local.`,
addresses: [`10.0.0.${index + 1}`],
}));
}
});
return browser;
}
destroy() {}
}
const rows = await scanCameras({ durationMs: 1000, maxResults: 3, BonjourClass: FakeBonjour });
assert.equal(rows.length, 3);
assert.equal(browserStopped, true);
});
+35
View File
@@ -0,0 +1,35 @@
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const root = path.join(__dirname, '..');
test('Electron boundary stays isolated and packaged files are declared', () => {
const main = fs.readFileSync(path.join(root, 'main.js'), 'utf8');
const preload = fs.readFileSync(path.join(root, 'preload.js'), 'utf8');
const appProtocol = fs.readFileSync(path.join(root, 'src', 'app-protocol.js'), 'utf8');
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
assert.match(main, /nodeIntegration:\s*false/);
assert.match(main, /contextIsolation:\s*true/);
assert.match(main, /sandbox:\s*true/);
assert.match(main, /isTrustedSender/);
assert.match(main, /setPermissionCheckHandler/);
assert.match(main, /setPermissionRequestHandler/);
assert.match(main, /registerSchemesAsPrivileged/);
assert.match(appProtocol, /app:\/\/bundle/);
assert.doesNotMatch(main, /\.loadFile\s*\(/);
assert.doesNotMatch(preload, /require\(['"](?:node:)?(?:fs|child_process|dgram)/);
assert.match(preload, /exportCsv:\s*\(\)\s*=>\s*ipcRenderer\.invoke\('export-csv'\)/);
assert.ok(pkg.build.files.includes('src/**/*'));
assert.ok(pkg.build.files.includes('static/**/*'));
assert.equal(pkg.build.win.icon, 'assets/icon.ico');
assert.equal(pkg.build.electronFuses.runAsNode, false);
assert.equal(pkg.build.electronFuses.enableNodeOptionsEnvironmentVariable, false);
assert.equal(pkg.build.electronFuses.enableNodeCliInspectArguments, false);
assert.equal(pkg.build.electronFuses.enableEmbeddedAsarIntegrityValidation, true);
assert.equal(pkg.build.electronFuses.onlyLoadAppFromAsar, true);
assert.equal(pkg.build.electronFuses.grantFileProtocolExtraPrivileges, false);
});
+72
View File
@@ -0,0 +1,72 @@
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const { createScanSession } = require('../src/scan-session');
const camera = {
alta_key: 'ABH7-C62U-GC3E',
hostname: 'avacam-abh7-c62u-gc3e.local',
web_ui_url: 'https://avacam-abh7-c62u-gc3e.local',
ip_address: '10.0.0.223',
port: 443,
service: '_vaioncam._tcp.local',
};
test('shares one scan, publishes defensive state, and binds camera URLs', async () => {
let scanCalls = 0;
let releaseScan;
const scan = () => {
scanCalls += 1;
return new Promise((resolve) => { releaseScan = resolve; });
};
const times = [1000, 2345];
const session = createScanSession({ scan, now: () => times.shift() });
const first = session.scanOnce();
const second = session.scanOnce();
assert.strictEqual(first, second);
assert.equal(scanCalls, 1);
assert.equal(session.allowedCameraUrl(camera.web_ui_url), null);
assert.deepEqual(session.getLatestCameras(), []);
releaseScan([camera]);
assert.deepEqual(await first, {
ok: true,
count: 1,
duration_seconds: 1.3,
cameras: [camera],
});
assert.equal(session.allowedCameraUrl(camera.web_ui_url), camera.web_ui_url);
assert.equal(session.allowedCameraUrl(`${camera.web_ui_url}/?secret=value`), null);
assert.equal(session.allowedCameraUrl('https://avacam-ahg2-z4nd-fvrn.local'), null);
const exposed = session.getLatestCameras();
exposed[0].alta_key = 'MUTATED';
assert.equal(session.getLatestCameras()[0].alta_key, camera.alta_key);
});
test('revokes prior state at rescan and permits retry after failure', async () => {
let call = 0;
let releaseSecondScan;
const scan = () => {
call += 1;
if (call === 1) return Promise.resolve([camera]);
if (call === 2) return new Promise((_resolve, reject) => { releaseSecondScan = reject; });
return Promise.resolve([camera]);
};
const session = createScanSession({ scan, now: () => 0 });
await session.scanOnce();
assert.equal(session.allowedCameraUrl(camera.web_ui_url), camera.web_ui_url);
const failed = session.scanOnce();
assert.equal(session.allowedCameraUrl(camera.web_ui_url), null);
assert.deepEqual(session.getLatestCameras(), []);
releaseSecondScan(new Error('network failed'));
await assert.rejects(failed, /network failed/);
const retried = await session.scanOnce();
assert.equal(call, 3);
assert.equal(retried.count, 1);
});
+23
View File
@@ -0,0 +1,23 @@
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const { isCameraUrl, normalizeCameraUrl } = require('../src/url-policy');
const cameraUrl = 'https://avacam-abh7-c62u-gc3e.local';
test('permits only root local Alta camera HTTPS URLs', () => {
assert.equal(isCameraUrl(cameraUrl), true);
assert.equal(isCameraUrl('http://avacam-abh7-c62u-gc3e.local'), false);
assert.equal(isCameraUrl('https://example.com'), false);
assert.equal(isCameraUrl('https://user:pass@avacam-abh7-c62u-gc3e.local'), false);
assert.equal(isCameraUrl('https://avacam-abh7-c62u-gc3e.local:8443'), false);
assert.equal(isCameraUrl(`${cameraUrl}/anything`), false);
assert.equal(isCameraUrl(`${cameraUrl}/?secret=value`), false);
assert.equal(isCameraUrl(`${cameraUrl}/#fragment`), false);
});
test('normalizes camera URLs to their canonical form', () => {
assert.equal(normalizeCameraUrl(`${cameraUrl}/`), cameraUrl);
assert.equal(normalizeCameraUrl(`${cameraUrl.toUpperCase()}/`), cameraUrl);
});