2026-10-13 18:04:02 +02:00
'use strict' ;
const { app , BrowserWindow , clipboard , dialog } = require ( 'electron' );
const fs = require ( 'node:fs' ), path = require ( 'node:path' ), assert = require ( 'node:assert/strict' );
app . setPath ( 'userData' , process . env . SAFETYNET_SMOKE_USERDATA ); app . disableHardwareAcceleration (); require ( '../apps/browser/main.cjs' );
const wait = ms => new Promise ( r => setTimeout ( r , ms ));
let stage = 'startup' , page , originalClipboard ;
async function until ( fn ){ const end = Date . now () + 45000 ; while ( Date . now () < end ){ if ( await fn ()) return ; await wait ( 100 );} throw Error ( `Fixture deadline: ${ stage } ` );}
app . whenReady (). then ( async ()=>{ try {
let win ; await until (()=>{ win = BrowserWindow . getAllWindows ()[ 0 ]; return win &&! win . webContents . isLoading () && win . webContents . getURL (). endsWith ( 'index.html' );}); await wait ( 300 );
const result = await win . webContents . executeJavaScript ( `window.safetynet.enroll( ${ JSON . stringify ({ server : process . env . SAFETYNET_SMOKE_SERVER , code : process . env . SAFETYNET_SMOKE_CODE } )})` ); assert . equal ( result . ok , true ); await wait ( 600 );
page = win . contentView . children . find ( v => v . webContents !== win . webContents ). webContents ;
const state = ()=> win . webContents . executeJavaScript ( 'window.safetynet.state()' ). then ( r => r . data ), base = process . env . SAFETYNET_SMOKE_SERVER ;
const headers = { authorization : `Bearer ${ process . env . SAFETYNET_SMOKE_ADMIN } ` , 'content-type' : 'application/json' };
const overview = ()=> fetch ( base + '/api/admin/overview' ,{ headers }). then ( r => r . json ());
const records = async ()=>(( await overview ()). events || []). filter ( e => e . kind === 'evidence.recorded' && e . metadata . evidenceType === 'interaction' );
async function key ( code ){ page . focus (); page . sendInputEvent ({ type : 'keyDown' , keyCode : code , modifiers : [ 'control' ]}); page . sendInputEvent ({ type : 'keyUp' , keyCode : code , modifiers : [ 'control' ]}); await wait ( 800 ); await until ( async ()=> ! ( await state ()). clipboardPending );}
originalClipboard = await clipboard . readText ();
stage = 'copy' ; await page . executeJavaScript ( "(()=>{const r=document.createRange();r.selectNodeContents(document.getElementById('clipboard-source'));const s=getSelection();s.removeAllRanges();s.addRange(r)})()" ); await key ( 'C' ); assert . equal ( await clipboard . readText (), 'Synthetic public selection' ); await until ( async ()=>( await records ()). length === 1 );
stage = 'paste' ; await clipboard . writeText ( 'Synthetic pasted text' ); await page . executeJavaScript ( "document.getElementById('public-input').focus()" ); await key ( 'V' ); assert . equal ( await page . executeJavaScript ( "document.getElementById('public-input').value" ), 'Synthetic pasted text' ); await until ( async ()=>( await records ()). length === 2 );
stage = 'cut' ; await page . executeJavaScript ( "(()=>{const e=document.getElementById('public-input');e.focus();e.select()})()" ); await key ( 'X' ); assert . equal ( await page . executeJavaScript ( "document.getElementById('public-input').value" ), '' ); assert . equal ( await clipboard . readText (), 'Synthetic pasted text' ); await until ( async ()=>( await records ()). length === 3 );
stage = 'password exclusion' ; await page . executeJavaScript ( "document.getElementById('private-input').focus()" ); await clipboard . writeText ( 'Synthetic password attempt' ); await key ( 'V' ); assert . equal ( await page . executeJavaScript ( "document.getElementById('private-input').value" ), 'never-export-this' ); await wait ( 600 ); assert . equal (( await records ()). length , 3 );
stage = 'agent click' ; const connection = await win . webContents . executeJavaScript ( 'window.safetynet.agentConnection()' ); assert . equal ( connection . ok , true );
const sessionId = ( await state ()). activeTabId , requestFile = path . join ( process . env . SAFETYNET_SMOKE_USERDATA , 'interaction-request.json' );
fs . writeFileSync ( requestFile , JSON . stringify ({ action : 'click' , args : { sessionId , selector : '#public-button' }}));
const child = require ( 'node:child_process' ). spawn ( process . execPath ,[ 'scripts/agent-client.cjs' , '--connection' , connection . data . credentialPath , '--request' , requestFile ],{ windowsHide : true , stdio : [ 'ignore' , 'pipe' , 'pipe' ]}); let output = '' ; child . stdout . on ( 'data' , c => output += c ); child . stderr . on ( 'data' ,()=>{}); const exit = await new Promise ( r =>{ child . once ( 'exit' , r ); child . once ( 'error' ,()=> r ( 1 ));}); assert . equal ( exit , 0 ); assert . equal ( JSON . parse ( output ). result . completed , true ); assert . equal ( await page . executeJavaScript ( "document.getElementById('public-button').dataset.clicked" ), '1' ); await until ( async ()=>( await records ()). length === 4 );
2026-10-13 18:24:44 +02:00
stage = 'human observer installation' ; await until (()=> page . executeJavaScriptInIsolatedWorld ( 998 ,[{ code : "!!globalThis.__safetynetHumanInteraction" }], false )); await page . executeJavaScript ( "window.__fixtureTrustedClick=false;window.addEventListener('click',e=>{window.__fixtureTrustedClick=e.isTrusted},true)" );
stage = 'synthetic human exclusion' ; await page . executeJavaScript ( "document.getElementById('public-button').click();document.getElementById('public-form').dispatchEvent(new Event('submit',{bubbles:true,cancelable:true}));document.getElementById('public-form').requestSubmit()" ); await wait ( 700 ); assert . equal (( await records ()). length , 4 );
async function physicalClick ( id ){ const point = await page . executeJavaScript ( `(()=>{const r=document.getElementById( ${ JSON . stringify ( id ) } ).getBoundingClientRect();return {x:Math.round(r.left+r.width/2),y:Math.round(r.top+r.height/2)}})()` ); page . focus (); page . sendInputEvent ({ type : 'mouseDown' , button : 'left' , clickCount : 1 ,... point }); page . sendInputEvent ({ type : 'mouseUp' , button : 'left' , clickCount : 1 ,... point }); await wait ( 900 );}
stage = 'physical click' ; await physicalClick ( 'public-button' ); assert . equal ( await page . executeJavaScript ( 'window.__fixtureTrustedClick' ), true ); assert . equal ( await page . executeJavaScript ( "document.getElementById('public-button').dataset.clicked" ), '3' ); await until ( async ()=>( await records ()). length === 5 );
stage = 'physical submit' ; await physicalClick ( 'submit-button' ); assert . equal ( await page . executeJavaScript ( "document.getElementById('public-form').dataset.submitted" ), '3' ); await until ( async ()=>( await records ()). length === 7 );
stage = 'private form exclusion' ; await physicalClick ( 'private-submit' ); await wait ( 500 ); assert . equal (( await records ()). length , 7 );
2026-10-13 18:04:02 +02:00
const recorded = await records (), payloads = [];
stage = 'analyst reveal' ; for ( const e of recorded ){ const response = await fetch ( base + `/api/admin/evidence/ ${ e . metadata . evidenceId } ?reason=investigation` ,{ headers }); assert . equal ( response . status , 200 ); const item = await response . json (); payloads . push ( item . payload );}
2026-10-13 18:24:44 +02:00
assert . deepEqual ( payloads . map ( p => p . action ). sort (),[ 'click' , 'click' , 'click' , 'copy' , 'cut' , 'paste' , 'submit' ]); assert . ok ( payloads . every ( p => p . sessionId === sessionId && p . sensitiveField === false )); assert . equal ( payloads . filter ( p => p . captureSource === 'human-observer' && p . outcome === 'observed' ). length , 3 ); assert . ok ( payloads . every ( p => p . pageUrl === new URL ( p . pageUrl ). origin + '/' )); assert . ok ( payloads . some ( p => p . action === 'click' && p . captureSource === 'agent-adapter' && p . target ? . tag === 'BUTTON' ));
2026-10-13 18:04:02 +02:00
const serialized = JSON . stringify ( payloads ), eventsBefore = ( await overview ()). events ;
2026-10-13 18:24:44 +02:00
for ( const marker of [ 'Synthetic public selection' , 'Synthetic pasted text' , 'Synthetic control label' , 'Synthetic password attempt' , 'never-export-this' , 'Synthetic private form field' , '#public-button' , '#private-input' ]){ assert . equal ( serialized . includes ( marker ), false ); assert . equal ( JSON . stringify ( eventsBefore ). includes ( marker ), false );}
assert . equal ( eventsBefore . filter ( e => e . kind === 'evidence.accessed' ). length , 7 );
2026-10-13 18:04:02 +02:00
stage = 'admin policy screenshot' ; const adminWindow = new BrowserWindow ({ width : 1440 , height : 1000 , show : false , webPreferences : { nodeIntegration : false , contextIsolation : true , sandbox : true }});
await adminWindow . webContents . session . cookies . set ({ url : base , name : 'sn_session' , value : process . env . SAFETYNET_SMOKE_REVIEWER , httpOnly : true , sameSite : 'strict' }); await adminWindow . loadURL ( base + '/' );
await until (()=> adminWindow . webContents . executeJavaScript ( "(()=>{const e=document.getElementById('evidence-policy-interactions');return !!e&&e.checked&&!e.disabled})()" ));
const crop = await adminWindow . webContents . executeJavaScript ( "(()=>{const section=document.getElementById('evidence-policy-controls');section.scrollIntoView({block:'start'});const r=section.getBoundingClientRect();return {x:Math.max(0,Math.floor(r.x)),y:Math.max(0,Math.floor(r.y)),width:Math.min(innerWidth-Math.max(0,Math.floor(r.x)),Math.ceil(r.width)),height:Math.min(innerHeight-Math.max(0,Math.floor(r.y)),Math.ceil(r.height))}})()" );
await wait ( 200 ); fs . writeFileSync ( path . resolve ( 'artifacts/interaction-evidence-admin-controls.png' ),( await adminWindow . webContents . capturePage ( crop )). toPNG ()); adminWindow . destroy ();
stage = 'independent policy review' ; const policy = ( await overview ()). policy ; policy . version ++ ; policy . evidence . captureInteractions = false ;
const proposed = await fetch ( base + '/api/admin/policy' ,{ method : 'PUT' , headers , body : JSON . stringify ( policy )}); assert . equal ( proposed . status , 202 ); const review = await proposed . json ();
const approved = await fetch ( base + `/api/admin/policy-reviews/ ${ review . reviewId } /approve` ,{ method : 'POST' , headers : { cookie : `sn_session= ${ process . env . SAFETYNET_SMOKE_REVIEWER } ` , origin : base , 'content-type' : 'application/json' }, body : JSON . stringify ({ payloadHash : review . payloadHash , expectedVersion : review . expectedVersion , approve : true })}); assert . equal ( approved . status , 200 ); await until ( async ()=>( await state ()). policyVersion === policy . version && ( await state ()). ready );
2026-10-13 18:24:44 +02:00
stage = 'disabled interaction' ; await page . executeJavaScript ( "document.getElementById('public-input').focus()" ); await clipboard . writeText ( 'Synthetic post-disable text' ); await key ( 'V' ); assert . equal ( await page . executeJavaScript ( "document.getElementById('public-input').value" ), 'Synthetic post-disable text' ); await wait ( 600 ); await physicalClick ( 'public-button' ); assert . equal (( await records ()). length , 7 );
2026-10-13 18:04:02 +02:00
stage = 'download independently enabled' ; dialog . showSaveDialog = async ()=>({ canceled : false , filePath : path . join ( process . env . SAFETYNET_SMOKE_USERDATA , 'safe.bin' )}); await page . executeJavaScript ( "document.getElementById('safe-download').click()" ); await until ( async ()=>{ const s = await state (); return s . ready && s . message === 'Download scanned and saved.' ;}); assert . deepEqual ( fs . readFileSync ( path . join ( process . env . SAFETYNET_SMOKE_USERDATA , 'safe.bin' )), Buffer . from ([ 0 , 1 , 2 , 3 , 255 ])); await until ( async ()=>(( await overview ()). events || []). some ( e => e . kind === 'evidence.recorded' && e . metadata . evidenceType === 'download' ));
2026-10-13 18:24:44 +02:00
const after = ( await overview ()). events , sources = recorded . map ( e => after . find ( source => source . id === e . metadata . sourceEventId )); assert . ok ( sources . every ( Boolean )); assert . ok ( sources . every ( e => e . metadata . traceId )); sources . sort (( a , b )=> Number ( b . kind === 'agent.action' ) - Number ( a . kind === 'agent.action' )); assert . equal ( sources . filter ( e => e . kind === 'browser.interaction' ). length , 3 );
fs . writeFileSync ( path . resolve ( 'artifacts/interaction-evidence-native-proof.json' ), JSON . stringify ({ actualElectron : true , physicalTrustedClickAndSubmit : true , syntheticHumanEventsExcluded : true , passwordFormsExcluded : true , humanObservationNotTransmission : true , nativeCopyPasteCut : true , agentClickExactlyOnce : true , passwordControlExcluded : true , noRawContentLabelsSelectors : true , completedActionsBoundToSession : true , analystAccessAudited : true , independentSignedDisable : true , actualAdminControlsScreenshot : true , disabledInteractionLeavesDownloadCapture : true , eventIds : sources . map ( e => e . id ), traceIds : sources . map ( e => e . metadata . traceId ), humanTraceIds : sources . filter ( e => e . kind === 'browser.interaction' ). map ( e => e . metadata . traceId ), humanEventIds : sources . filter ( e => e . kind === 'browser.interaction' ). map ( e => e . id )}, null , 2 ));
2026-10-13 18:04:02 +02:00
console . log ( 'Native protected interaction evidence proof passed.' ); await clipboard . writeText ( originalClipboard ); require ( '../apps/browser/page-clipboard-guard.cjs' ). disposePageClipboardGuard ( page ); app . exit ( 0 );
2026-10-13 18:24:44 +02:00
} catch ( error ){ if ( originalClipboard !== undefined ) await clipboard . writeText ( originalClipboard ); if ( page ) require ( '../apps/browser/page-clipboard-guard.cjs' ). disposePageClipboardGuard ( page ); let checkpoint = {}; try { if ( page &&! page . isDestroyed ()) checkpoint . observer = await page . executeJavaScriptInIsolatedWorld ( 998 ,[{ code : "(()=>{const s=globalThis.__safetynetHumanInteraction;return {installed:!!s,pending:s?.queue?.length||0,dropped:s?.dropped||0}})()" }], false ); const queuePath = path . join ( process . env . SAFETYNET_SMOKE_USERDATA , 'audit-queue.bin' ); if ( fs . existsSync ( queuePath )){ const queue = JSON . parse ( require ( 'electron' ). safeStorage . decryptString ( fs . readFileSync ( queuePath ))); checkpoint . pendingHumanSources = queue . filter ( e => e . kind === 'browser.interaction' ). slice ( 0 , 16 ). map (({ eventId , traceId , spanId , policyVersion })=>({ eventId , traceId , spanId , policyVersion }));}} catch {} fs . writeFileSync ( path . resolve ( 'artifacts/interaction-evidence-native-error.json' ), JSON . stringify ({ stage , name : error . name , message : error . message , checkpoint }, null , 2 )); console . error ( `Interaction evidence fixture failed at ${ stage } : ${ error . name } ` ); app . exit ( 1 );}});