Files
ycode/scripts/rea/cpp-expert-materialize.mjs
T

8 lines
1.4 KiB
JavaScript

/** Review copies only from retained REA text, never from original filesystem. */
import fs from 'node:fs'
import path from 'node:path'
import crypto from 'node:crypto'
const root='.tmp/rea-cpp-expert-recovered-20261016',pin='b90023e9622bd74c55d583051bee3625eb491b552baeea17ae10ac792a352498',manifest={rootSha256:pin,files:[]}
for(const input of process.argv.slice(2)){const evidence=JSON.parse(fs.readFileSync(input,'utf8'));if(evidence.normalized_result.root_sha256!==pin)throw Error('Root mismatch');for(const f of evidence.normalized_result.files){const sha=crypto.createHash('sha256').update(f.text).digest('hex');if(sha!==f.sha256||Buffer.byteLength(f.text)!==f.size_bytes)throw Error('Text byte mismatch');if(f.path.split('/').some(p=>!p||p==='.'||p==='..')||f.path.includes('\\'))throw Error('Canonical path required');const output=path.join(root,...f.path.split('/'));fs.mkdirSync(path.dirname(output),{recursive:true});fs.writeFileSync(output,f.text);if(crypto.createHash('sha256').update(fs.readFileSync(output)).digest('hex')!==sha)throw Error('Recovered file SHA mismatch');manifest.files.push({path:f.path,bytes:f.size_bytes,sha256:f.sha256,evidenceId:evidence.evidence_id,retainedExport:input})}}
fs.writeFileSync(path.join(root,'evidence-manifest.json'),JSON.stringify(manifest,null,2)+'\n');console.log(JSON.stringify({root,files:manifest.files.length,bytes:manifest.files.reduce((n,f)=>n+f.bytes,0)}))