Files
Investidor-V2/tools/investment-preparation-proof.mjs
T

19 lines
4.3 KiB
JavaScript

import fs from 'node:fs';
import path from 'node:path';
import assert from 'node:assert/strict';
import {createHash} from 'node:crypto';
import JSZip from 'jszip';
const out=new URL('../outputs/investment-preparation-20261110/',import.meta.url);
const read=name=>JSON.parse(fs.readFileSync(new URL(name,out),'utf8'));
const digest=bytes=>createHash('sha256').update(bytes).digest('hex');
const api=read('apiex-recovered.json'),swot=read('swot-recovered.json'),sources=read('source-changes.json'),scopes=read('opportunity-scopes.json'),history=read('history-pages.json'),security=read('archive-security.json');
const bytes=fs.readFileSync(new URL('apiex-package.zip',out)),zip=await JSZip.loadAsync(bytes),manifest=JSON.parse(await zip.file('manifesto.json').async('string'));
assert.equal(manifest.case_id,api.case.id);assert.equal(api.api_state,'decision_received');assert.deepEqual(api.apiex.external.map(x=>x.kind),['delivery','clarification','response','decision']);assert.equal(api._qa_archive.initial_sha256,api._qa_archive.after_context_change_sha256);assert.equal(digest(bytes),api._qa_archive.initial_sha256);assert.equal(manifest.export.id,api.apiex.exports[0].id);assert.deepEqual(manifest.export.prepared.context,manifest.context);assert.notEqual(manifest.context.fields.project_summary,api.context.fields.project_summary);
for(const [n,doc] of manifest.export.documents.entries()){const name='anexos/'+String(n+1).padStart(2,'0')+'-'+doc.file_name.replace(/[^\p{L}\p{N}._-]+/gu,'-');assert.equal(digest(await zip.file(name).async('nodebuffer')),doc.sha256);}
assert.equal(new Set(swot.swot.rows.map(r=>r.dimension)).size,4);assert.ok(swot.swot.rows.every(r=>r.reference&&r.date&&['documented_fact','hypothesis','unconfirmed'].includes(r.classification)));assert.equal(swot.swot.actions[0].case_id,swot.case.id);assert.equal(swot._qa_native_task.case_id,swot.case.id);assert.equal(swot._qa_native_task.title,swot.swot.actions[0].title);assert.equal(swot._qa_native_task.origin_key,'swot:'+swot.swot.actions[0].id);assert.ok(swot.swot.sources_snapshot);assert.ok(swot.history.some(h=>h.action==='swot_review'));assert.equal(sources.approved_fingerprint,sources.private_edit_fingerprint);assert.notEqual(sources.approved_fingerprint,sources.new_public_fingerprint);assert.equal(sources.withdrawal_review_required,true);assert.equal(sources.conclusions_preserved,true);assert.equal(scopes.second_version_unchanged,0);assert.equal(scopes.retired_scope_readable,true);assert.equal(scopes.retired_scope_writable,false);assert.deepEqual(history.next_versions,[2,1]);assert.equal(security.revoked_scan_cached_download_status,404);assert.ok(security.encrypted_archive_count>0);
const preview=new URL('apiex-preview/',out);fs.mkdirSync(preview,{recursive:true});
for(const entry of Object.values(zip.files)){if(entry.dir)continue;const root=path.resolve(decodeURIComponent(preview.pathname).replace(/^\/([A-Za-z]:)/,'$1')),target=path.resolve(root,entry.name);assert.ok(target.startsWith(root+path.sep));fs.mkdirSync(path.dirname(target),{recursive:true});fs.writeFileSync(target,await entry.async('nodebuffer'));}
fs.writeFileSync(new URL('swot-recovered.pretty.json',out),JSON.stringify(swot,null,2));
const proof={synthetic:true,apiEx:{path:'existing dossier → requirements → documents → review → ZIP/index/attachments → external delivery/clarification/response/decision',archive_sha256:digest(bytes),attachments_verified:manifest.export.documents.length,preserved_after_context_change:true,no_automatic_submission_or_approval:true},swot:{path:'existing context/evidence → four dimensions → review → linked native task in same dossier → recovery',private_by_default:true,classification_source_date_preserved:true,source_versions_preserved:true,changed_public_sources_require_review:true,private_source_edits_not_exposed:true,deliberate_edits_preserved:true},scope_isolation:true,historical_scopes_readable_without_reactivation:true,history_beyond25:true,malware_guard_on_archived_download:true,qa_database:'simulator_fiscal_delta_20261021_test',qa_port:55441,database_transactions:'rolled back by native test trait; QA sequences may advance',installed:false,browser_visual_review:'pending; connector unavailable',no_new_database_or_port_or_migration_or_real_account:true};
fs.writeFileSync(new URL('verification.json',out),JSON.stringify(proof,null,2));console.log(JSON.stringify(proof));