Publish verified traceability view Windows evidence
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// Evidence serialization only. Root supplies a freshly observed Sky state.
|
||||
globalThis.captureTraceability = async function(name, note, currentState) {
|
||||
if (!/^[a-zA-Z0-9_-]+$/.test(name)) throw Error('Invalid capture name');
|
||||
if (!currentState?.screenshots?.length) throw Error('Fresh screenshot required');
|
||||
const {fileURLToPath} = await import('node:url');
|
||||
const root = fileURLToPath(new URL('.', import.meta.url)).replaceAll('\\','/').replace(/\/$/,'');
|
||||
const run = globalThis.traceabilityRunRoot;
|
||||
if (!run || !run.startsWith(root+'/runs/run-')) throw Error('Bind current run first');
|
||||
const file = await import('node:fs/promises');
|
||||
const crypto = await import('node:crypto');
|
||||
const hash = bytes => crypto.createHash('sha256').update(bytes).digest('hex');
|
||||
const launchBytes = await file.readFile(run+'/launch.json');
|
||||
const launch = JSON.parse(launchBytes.toString('utf8').replace(/^\uFEFF/,''));
|
||||
const manifestBytes = await file.readFile(root+'/input-manifest.json');
|
||||
if (hash(manifestBytes) !== launch.manifest_sha256) throw Error('Manifest changed');
|
||||
const manifest = JSON.parse(manifestBytes.toString('utf8').replace(/^\uFEFF/,''));
|
||||
const saved = manifest.saved_working_path;
|
||||
const savedExists = await file.access(saved).then(()=>true,()=>false);
|
||||
const workingPath = savedExists ? saved : manifest.initial_working.path;
|
||||
const working = await file.readFile(workingPath);
|
||||
const dir = run+'/captures';
|
||||
await file.mkdir(dir,{recursive:true});
|
||||
const images=[];
|
||||
for (let i=0;i<currentState.screenshots.length;i++) {
|
||||
const s=currentState.screenshots[i];
|
||||
const mime=s.url.slice(5,s.url.indexOf(';'));
|
||||
if (!['image/jpeg','image/png'].includes(mime)) throw Error('Unexpected image type');
|
||||
const bytes=Buffer.from(s.url.split(',')[1],'base64');
|
||||
const filename=name+(i ? '-'+i : '')+(mime==='image/jpeg'?'.jpg':'.png');
|
||||
await file.writeFile(dir+'/'+filename,bytes,{flag:'wx'});
|
||||
images.push({file:filename,id:s.id,width:s.width,height:s.height,originX:s.originX,originY:s.originY,zIndex:s.zIndex,mime,bytes:bytes.length,sha256:hash(bytes)});
|
||||
}
|
||||
const record={utc:new Date().toISOString(),source_commit:launch.source_commit,launch_sha256:hash(launchBytes),pid:launch.pid,process_started_utc:launch.started_utc,manifest_sha256:launch.manifest_sha256,window:currentState.window,images,working_source_path:workingPath,working_source_sha256:hash(working),note};
|
||||
await file.writeFile(dir+'/'+name+'.json',JSON.stringify(record,null,2)+'\n',{flag:'wx'});
|
||||
return {name,images:images.length,source_commit:record.source_commit};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user