Files
safetynet/scripts/policy-history-admin-smoke.cjs
T

27 lines
5.9 KiB
JavaScript
Raw Normal View History

2026-10-13 10:33:31 +02:00
'use strict';
const {app,BrowserWindow}=require('electron');const assert=require('node:assert/strict');const fs=require('node:fs');const path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);app.commandLine.appendSwitch('force-device-scale-factor','1');
let window;const deadline=setTimeout(()=>{console.error('ADMIN_UI_PROOF_TIMEOUT');app.exit(1);},50000);
async function evaluate(source){return window.webContents.executeJavaScript(source,true);}
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Administrator UI state did not arrive');}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
await evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require,bridge:typeof safetynet})`),{node:'undefined',require:'undefined',bridge:'undefined'});
const headers=await evaluate(`fetch(location.href).then(r=>({csp:r.headers.get('content-security-policy'),type:r.headers.get('x-content-type-options')}))`);assert.ok(headers.csp.includes("script-src 'self'"));assert.ok(headers.csp.includes("frame-ancestors 'none'"));assert.equal(headers.type,'nosniff');
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);
await evaluate(`document.getElementById('brand-name').value='History test brand';document.getElementById('security-dns-hosts').value='blocked.synthetic.example';document.getElementById('security-dns-ips').value='203.0.113.10';document.getElementById('security-content-phrases').value='synthetic forbidden project';document.getElementById('agent-enabled').checked=true;document.getElementById('agent-hosts').value='*.synthetic.example';document.getElementById('agent-scope-read').checked=true;document.getElementById('publish').click()`);
await waitFor(`document.getElementById('policy-version').textContent==='v2'&&document.getElementById('status').textContent.includes('published')`);
assert.equal(await evaluate(`document.getElementById('security-dns-hosts').value`),'blocked.synthetic.example');assert.equal(await evaluate(`document.getElementById('agent-enabled').checked`),true);assert.equal(await evaluate(`document.getElementById('agent-scope-read').checked`),true);
await evaluate(`document.getElementById('security-controls').scrollIntoView()`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,200));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/admin-security-controls.png'),(await window.webContents.capturePage()).toPNG());
await evaluate(`document.getElementById('brand-name').value='Unpublished draft';document.getElementById('history-load').click()`);await waitFor(`document.querySelectorAll('#history-rows tr').length===2`);
assert.equal(await evaluate(`document.getElementById('brand-name').value`),'Unpublished draft');
await evaluate(`document.querySelectorAll('#history-rows button')[1].click()`);await waitFor(`!document.getElementById('history-review').hidden`);
assert.equal(await evaluate(`document.getElementById('history-restore').disabled`),true);assert.equal(await evaluate(`document.getElementById('brand-name').value`),'Unpublished draft');assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v2');assert.ok((await evaluate(`document.getElementById('history-diff-list').textContent`)).includes('/brand/name'));
await evaluate(`document.getElementById('history-review').scrollIntoView();document.getElementById('console-theme').value='dark';document.getElementById('console-theme').dispatchEvent(new Event('change'))`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,300));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/policy-history-admin.png'),(await window.webContents.capturePage()).toPNG());
await evaluate(`globalThis.__originalPrincipal=currentPrincipal;applyOperatorPermissions({sub:'synthetic-auditor',role:'auditor',permissions:['overview.read','audit.read','policy.read','teaching.read']});`);assert.equal(await evaluate(`document.getElementById('history-approve').disabled&&document.getElementById('history-restore').disabled&&document.getElementById('agent-enabled').disabled`),true);await evaluate(`applyOperatorPermissions(globalThis.__originalPrincipal);delete globalThis.__originalPrincipal`);
await evaluate(`document.getElementById('history-approve').checked=true;document.getElementById('history-approve').dispatchEvent(new Event('change'));document.getElementById('history-restore').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v3'&&document.getElementById('status').textContent.includes('restored')`);
assert.equal(await evaluate(`document.getElementById('brand-name').value`),'SafetyNet');assert.equal(await evaluate(`document.getElementById('agent-enabled').checked`),false);assert.equal(await evaluate(`document.getElementById('security-dns-hosts').value`),'');assert.equal(await evaluate(`document.querySelectorAll('#history-rows tr').length`),3);assert.equal(await evaluate(`globalThis.__proofErrors`),0);
console.log('HISTORY_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('HISTORY_ADMIN_PROOF_FAILED',error.message);clearTimeout(deadline);window?.destroy();app.exit(1);});