chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,49 @@
|
||||
// Native metadata diagnostic owned by the local REA provider. No target injection or termination.
|
||||
import { spawn } from 'node:child_process';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
import { createEvidence } from '../domain/evidence.js';
|
||||
export async function inspectDesktopElectronProcesses(processName) {
|
||||
if (process.platform !== 'win32') throw new Error('Windows process metadata provider requires Windows');
|
||||
if (!/^[A-Za-z0-9_.-]{1,80}\.exe$/i.test(processName)) throw new Error('Select one literal executable basename');
|
||||
const script = `$targets=Get-CimInstance Win32_Process -Filter "Name='${processName}'"; $rows=foreach($p in $targets){$debugPort=$null;$processType='main';if($p.CommandLine -match '--remote-debugging-port[= ]+(\\d+)'){$debugPort=[int]$Matches[1]};if($p.CommandLine -match '--type[= ]+([^\\s]+)'){$processType=$Matches[1]};[pscustomobject]@{pid=$p.ProcessId;parentPid=$p.ParentProcessId;executable=$p.ExecutablePath;type=$processType;debugPort=$debugPort}};$listeners=Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue|Where-Object{$_.OwningProcess -in $targets.ProcessId}|Select-Object LocalAddress,LocalPort,OwningProcess;[pscustomobject]@{processes=@($rows);listeners=@($listeners)}|ConvertTo-Json -Depth 5 -Compress`;
|
||||
const result = await new Promise((resolve,reject)=>{
|
||||
const child=spawn('C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe',['-NoLogo','-NoProfile','-NonInteractive','-EncodedCommand',Buffer.from(script,'utf16le').toString('base64')],{windowsHide:true,stdio:['ignore','pipe','pipe']});
|
||||
const chunks=[];let size=0;const timer=setTimeout(()=>{child.kill();reject(new Error('Windows metadata query timed out'))},15000);
|
||||
child.stdout.on('data',chunk=>{size+=chunk.length;if(size>1024*1024){child.kill();reject(new Error('Windows metadata budget exceeded'))}else chunks.push(chunk)});
|
||||
child.stderr.on('data',()=>{});
|
||||
child.once('error',error=>{clearTimeout(timer);reject(error)});
|
||||
child.once('close',code=>{clearTimeout(timer);if(code!==0)return reject(new Error('Windows metadata query failed'));try{resolve(JSON.parse(Buffer.concat(chunks).toString('utf8').replace(/^\uFEFF/,'')))}catch(error){reject(error)}});
|
||||
});
|
||||
return createEvidence(undefined,{id:'rea-windows-electron-processes',name:'Local REA Windows Electron metadata provider',version:'1+state-local.1'},{
|
||||
predicateType:'rea.desktop-electron-processes',operation:'inspect_desktop_electron_processes',parameters:{process_name:processName},result,
|
||||
confidence:'observed',authority:'external-service',environment:{id:`${os.platform()}-${os.release()}`,platform:os.platform(),architecture:os.arch(),isolation:'none'},
|
||||
limitations:['Native process metadata and listening sockets only; no target injection, file extraction, restart or termination.','Command lines are reduced to process type and declared remote-debugging port; other argument values are omitted.']
|
||||
});
|
||||
}
|
||||
|
||||
// Explicit lifecycle operation. The caller must already have authorization to interrupt WorkBuddy.
|
||||
export async function restartDesktopElectronDebug(executable,port,authorized) {
|
||||
if(process.platform!=='win32'||authorized!==true)throw new Error('An authorized Windows restart is required');
|
||||
if(!Number.isInteger(port)||port<1024||port>65535)throw new Error('Select one debugging port from 1024 to 65535');
|
||||
const expected=path.join(process.env.LOCALAPPDATA,'Programs','WorkBuddy','WorkBuddy.exe');
|
||||
const actual=await fs.realpath(executable),allowed=await fs.realpath(expected);
|
||||
if(actual.toLowerCase()!==allowed.toLowerCase())throw new Error('Restart is limited to the installed WorkBuddy executable');
|
||||
const quoted=actual.replaceAll("'","''");
|
||||
const script=`$ErrorActionPreference='Stop';$exe='${quoted}';$before=@(Get-CimInstance Win32_Process -Filter "Name='WorkBuddy.exe'"|Where-Object{$_.ExecutablePath -eq $exe});$close=@();foreach($p in $before){$native=Get-Process -Id $p.ProcessId -ErrorAction SilentlyContinue;if($native -and $native.MainWindowHandle -ne 0){$close+= [pscustomobject]@{pid=$p.ProcessId;requested=$native.CloseMainWindow()}}};$deadline=[datetime]::UtcNow.AddSeconds(8);do{$remaining=@(Get-CimInstance Win32_Process -Filter "Name='WorkBuddy.exe'"|Where-Object{$_.ExecutablePath -eq $exe});if($remaining.Count -eq 0){break};Start-Sleep -Milliseconds 200}while([datetime]::UtcNow -lt $deadline);$forced=@();foreach($p in $before){$current=Get-CimInstance Win32_Process -Filter ("ProcessId="+$p.ProcessId);if($current -and $current.ExecutablePath -eq $exe -and $current.CreationDate -eq $p.CreationDate){Stop-Process -Id $p.ProcessId -Force -ErrorAction SilentlyContinue;$forced+=$p.ProcessId}};$deadline=[datetime]::UtcNow.AddSeconds(4);do{$remaining=@(Get-CimInstance Win32_Process -Filter "Name='WorkBuddy.exe'"|Where-Object{$_.ExecutablePath -eq $exe});if($remaining.Count -eq 0){break};Start-Sleep -Milliseconds 100}while([datetime]::UtcNow -lt $deadline);if($remaining.Count -ne 0){throw 'Selected WorkBuddy processes did not exit; no replacement was launched'};[pscustomobject]@{beforePids=@($before|ForEach-Object{$_.ProcessId});closeRequests=@($close);forcedPids=@($forced);remaining=0}|ConvertTo-Json -Depth 4 -Compress`;
|
||||
const stopped=await new Promise((resolve,reject)=>{
|
||||
const child=spawn('C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe',['-NoLogo','-NoProfile','-NonInteractive','-EncodedCommand',Buffer.from(script,'utf16le').toString('base64')],{windowsHide:true,stdio:['ignore','pipe','pipe']});
|
||||
let output='',errors='';const timer=setTimeout(()=>{child.kill();reject(new Error('Authorized restart shutdown timed out'))},20000);
|
||||
child.stdout.on('data',b=>{output+=b;if(output.length>65536){child.kill();reject(new Error('Restart result budget exceeded'))}});child.stderr.on('data',b=>errors+=b);
|
||||
child.once('error',e=>{clearTimeout(timer);reject(e)});child.once('close',code=>{clearTimeout(timer);if(code!==0)return reject(new Error('Restart shutdown failed: '+errors.slice(0,1000)));try{resolve(JSON.parse(output.replace(/^\uFEFF/,'')))}catch(e){reject(e)}});
|
||||
});
|
||||
const env={...process.env};for(const key of Object.keys(env))if(key.toUpperCase()==='ELECTRON_RUN_AS_NODE')delete env[key];
|
||||
const args=[`--remote-debugging-port=${port}`,'--remote-debugging-address=127.0.0.1'];
|
||||
const launched=spawn(actual,args,{detached:true,windowsHide:true,stdio:'ignore',env});
|
||||
await new Promise((resolve,reject)=>{launched.once('spawn',resolve);launched.once('error',reject)});launched.unref();
|
||||
return createEvidence(undefined,{id:'rea-windows-electron-processes',name:'Local REA Windows Electron lifecycle provider',version:'1+state-local.2'},{
|
||||
predicateType:'rea.desktop-electron-restart',operation:'restart_desktop_electron_debug',parameters:{executable:actual,port,restart_authorized:true},result:{...stopped,launchedPid:launched.pid,arguments:args},confidence:'observed',authority:'controlled-replay',environment:{id:`${os.platform()}-${os.release()}`,platform:os.platform(),architecture:os.arch(),isolation:'none'},
|
||||
limitations:['Caller-authorized restart can interrupt in-flight tasks.','Graceful close is attempted first; surviving launch identities belonging to the exact selected executable are terminated.','Launch evidence confirms process creation only; inspect the debugging endpoint separately.','No original file contents or application data are extracted by this lifecycle operation.']
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user