reprochain-ai / verify_bundle.js
Hugdrigo's picture
Upload 35 files
c04328a verified
Raw History Blame Contribute Delete
1.28 kB
#!/usr/bin/env node
/* ReproChain AI | local content-addressed artifact verification. MIT. */
'use strict';
const fs=require('node:fs'),path=require('node:path'),crypto=require('node:crypto');
const R=require('./reprochain_engine.js');
const root=__dirname;
const sha256=x=>crypto.createHash('sha256').update(x).digest('hex');
function main(){
const m=JSON.parse(fs.readFileSync(path.join(root,'manifest.json'),'utf8'));
R.validateManifest(m);
const expectRoot=sha256(R.merkleInput(m));
const rootPass=expectRoot===m.bundleRoot;
console.log(`Manifest root: ${rootPass?'MATCH':'FAIL'} ${expectRoot}`);
const statuses={};let n=0;
for(const a of m.artifacts){const f=path.join(root,a.file);const observed=fs.existsSync(f)?sha256(fs.readFileSync(f)):null;const pass=observed===a.sha256;statuses[a.id]={observed,match:pass};console.log(`${pass?'MATCH':'FAIL '} ${a.id.padEnd(20)} ${a.file}`);if(pass)n++;}
const audit=R.integrity(m,statuses);
console.log(`Integrity: ${n}/${m.artifacts.length} match; lineage graph acyclic; bundle root ${rootPass?'valid':'invalid'}.`);
return audit.passed&&rootPass?0:3;
}
if(require.main===module){try{process.exitCode=main();}catch(e){console.error('REPROCHAIN INTEGRITY ERROR:',e.message);process.exitCode=1;}}
module.exports={main};