/** Exercise the exact release bytes in isolated local directories, never the production root. */ import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; import assert from 'node:assert/strict'; import {createServer} from 'node:http'; import {spawn} from 'node:child_process'; import {pathToFileURL} from 'node:url'; const root=path.resolve('artifacts/ksf-development-references-20261108-r15/package'); const work=path.resolve('work/ksf-development-references-20261108-r15'); const target=fs.mkdtempSync(path.join(work,'publisher-check-')); const sha=b=>crypto.createHash('sha256').update(b).digest('hex'); const manifest=JSON.parse(fs.readFileSync(path.join(root,'deploy/industry-ui-files.json'))); const {publishFiles}=await import(pathToFileURL(path.join(root,'scripts/publish-industry-ui.mjs'))); const {rollbackFiles}=await import(pathToFileURL(path.join(root,'scripts/rollback-ui.mjs'))); const options={sourceDir:path.join(root,'payload'),manifestPath:path.join(root,'deploy/industry-ui-files.json'),targetDir:target}; const receipt={ok:false,checks:[],testedFilesSha256:{},productionWrites:0,paidCalls:0,localFilesystemOnly:true}; const check=(name,condition)=>{assert.ok(condition,name);receipt.checks.push(name);}; for(const name of ['index.html',...manifest.files.filter(f=>!f.allowMissing).map(f=>f.path)]){ const dest=path.join(target,name);fs.mkdirSync(path.dirname(dest),{recursive:true});fs.copyFileSync(path.join(work,'baseline',name),dest); } let server; try{ const dry=publishFiles(options);check('dry-plan-six-no-write',dry.readOnly&&dry.changes.length===6&&dry.backup===null); for(const f of manifest.files.filter(f=>f.allowMissing))assert.ok(!fs.existsSync(path.join(target,f.path))); const apply=publishFiles({...options,apply:true});check('apply-six-files',apply.filesystemVerified&&apply.changes.length===6); const noop=publishFiles({...options,apply:true});check('idempotent-no-op',noop.changes.length===0&&noop.backup===null); server=createServer(async(req,res)=>{ if(req.url==='/api/library'){ let body='';for await(const chunk of req)body+=chunk; const parsed=JSON.parse(body);assert.equal(parsed.op,'summary'); const upstream=await fetch('https://kangshifu.fmode.cn/api/library',{method:'POST',headers:{'content-type':'application/json'},body}); res.writeHead(upstream.status,{'content-type':'application/json'});res.end(await upstream.text());return; } const name=new URL(req.url,'http://localhost').pathname.slice(1); const file=path.resolve(target,name); if(!file.startsWith(target+path.sep)||!fs.existsSync(file)){res.writeHead(404);res.end();return;} res.writeHead(200,{'content-type':file.endsWith('.json')?'application/json':file.endsWith('.js')?'text/javascript':'text/html'});res.end(fs.readFileSync(file)); }); await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve)); const origin='http://127.0.0.1:'+server.address().port; const verify=await new Promise((resolve,reject)=>{ const child=spawn(process.execPath,[path.join(root,'scripts/verify-public.mjs'),'--origin',origin],{windowsHide:true}); let out='',err='';child.stdout.on('data',b=>out+=b);child.stderr.on('data',b=>err+=b);child.on('error',reject); child.on('close',code=>resolve({code,out,err})); }); const publicCheck=JSON.parse(verify.out);check('isolated-http-readback-with-live-library',verify.code===0&&publicCheck.ok); fs.writeFileSync(path.join(root,'evidence/isolated-public-check.json'),JSON.stringify(publicCheck,null,2)+'\n'); const rdry=rollbackFiles({targetDir:target,backupDir:apply.backup});check('rollback-dry-six-files',rdry.readOnly&&rdry.changes.length===6); const restored=rollbackFiles({targetDir:target,backupDir:apply.backup,apply:true});check('rollback-restores-baseline',restored.filesystemVerified); check('rollback-noop',rollbackFiles({targetDir:target,backupDir:apply.backup}).changes.length===0); const corrupt=path.join(target,'src/pages/view-industry.js');fs.appendFileSync(corrupt,'\n// external change\n'); assert.throws(()=>publishFiles(options),{code:'UNKNOWN_TARGET_CONTENT'});check('unknown-target-stops',true); receipt.ok=true; for(const dir of ['payload','scripts','test','test-support','deploy']){ for(const entry of fs.readdirSync(path.join(root,dir),{recursive:true,withFileTypes:true})){ if(entry.isFile()){const file=path.join(entry.parentPath,entry.name),name=path.relative(root,file).replaceAll('\\','/');receipt.testedFilesSha256[name]=sha(fs.readFileSync(file));} } } }finally{ if(server)await new Promise(r=>server.close(r)); fs.writeFileSync(path.join(root,'evidence/package-acceptance.json'),JSON.stringify(receipt,null,2)+'\n'); console.log(JSON.stringify(receipt)); }