aere-quantum/control-plane/control-negativ-organizatie.mjs

113 lines
14 KiB
JavaScript

// Controlul negativ al probei judecatii organizatiei (proba-organizatie.mjs). Fiecare paznic al lui organizatie.mjs e scos, pe rand, intr-o COPIE
// pusa langa original (`_plantat-org-<pid>-<n>.mjs`, ca importurile relative sa ramana aceleasi), prin o conditie falsa LA RULARE sau o
// valoare schimbata (copia trebuie sa se poata incarca, altfel nu masoara nimic); proba ruleaza pe copie (AERE_ORG_MODUL) randurile care pazesc
// acel lucru (AERE_ORG_DOAR), iar randul NUMIT trebuie sa iasa rosu, cu proba chiar rulata pana la rezumat. Pe copia neatinsa, toata proba verde.
// Trei stari: ROSU cum trebuia (bine); CONTROL CAZUT (randul a ramas verde); STRICAT (tiparul nu apare exact o data, sau proba nu a ajuns la
// rezumat: o plantare care nu se poate pune e un ESEC al controlului, nu o linie de informare). La capat: nicio copie plantata ramasa.
// Reteaua: toate rularile primesc un capat de lant INCHIS (127.0.0.1:9), deci nicio plantare (nici "online mereu") nu atinge internetul.
// node control-negativ-organizatie.mjs iesire 0 = martorul verde si fiecare plantare rosie pe randul ei
import fs from 'node:fs';
import path from 'node:path';
import { spawn } from 'node:child_process';
import { fileURLToPath } from 'node:url';
const AICI = path.dirname(fileURLToPath(import.meta.url));
const SURSA = path.join(AICI, 'organizatie.mjs');
const PROBA = path.join(AICI, 'proba-organizatie.mjs');
const INCHIS = 'http://127.0.0.1:9';
// [ce se scoate, tiparul (exact o data in organizatie.mjs), inlocuirea, randul probei care trebuie sa iasa rosu]
const PLANTARI = [
['domeniul ia cel mai BUN artefact al lui', ' const verdict = celMaiSlab(ale.map((r) => r.verdict));', ' const verdict = ale.map((r) => r.verdict).reduce((a, b) => (RANG[b] > RANG[a] ? b : a));', 'stricat envelope:'],
['rezumatul ia cel mai BUN domeniu cerut', ' let verdict = celMaiSlab(vs);', ' let verdict = vs.reduce((a, b) => (RANG[b] > RANG[a] ? b : a));', 'pachetul bun: rezumatul'],
['un domeniu cerut si neprezentat numarat VALID in rezumat', "(d.verdict === 'NOT_PRESENTED' ? 'NOT_MEASURED' : d.verdict)", "(d.verdict === 'NOT_PRESENTED' ? 'VALID' : d.verdict)", 'domeniu neprezentat: NOT_PRESENTED'],
['adaptorul lipsa da VALID', "items.map(() => ({ error: `the conformance adapter is not at ${adaptor}: no verifier was run` }))",
"items.map(() => ({ v: 1, verdict: 'VALID', failed: [], levels: NIVELURI.map((l, i) => ({ level: l, state: i ? 'NOT_MEASURED' : 'PASSED', rules: [], cause: i ? 'not-judged' : undefined, reason: 'planted' })) }))", 'adaptorul suitei lipsa'],
['adaptorul lipsa da INVALID', "items.map(() => ({ error: `the conformance adapter is not at ${adaptor}: no verifier was run` }))",
"items.map(() => ({ v: 1, verdict: 'INVALID', failed: ['planted'], levels: NIVELURI.map((l, i) => ({ level: l, state: i ? 'NOT_MEASURED' : 'FAILED', rules: i ? [] : ['planted'], cause: i ? 'not-judged' : undefined, reason: 'planted' })) }))", 'adaptorul suitei lipsa'],
['eroarea unui verificator ignorata (verificatorul de referinta lipsa)', '} else { const a = verdicte[x.lot]; if (a.error) eroare = a.error; else v = a; }', "} else { const a = verdicte[x.lot]; if (a.error && false) eroare = a.error; else v = a.error ? { verdict: 'VALID', failed: [], levels: [] } : a; }", 'verificatorul de referinta AIP-23 lipsa'],
['un lot cu mai putine verdicte decat artefacte crezut', ' const motiv = linii.length === items.length ? null :', ' const motiv = true ? null :', 'mai putine verdicte'],
['un verdict incoerent al adaptorului crezut', ' if (formaVerdictului(j, cauzePartiale)) return j;', ' if (formaVerdictului(j, cauzePartiale) || (j && j.verdict)) return j;', 'verdict incoerent'],
// revizia B2 (2026-10-21): paznicii noi, fiecare cu randul probei care il arata
['verdictul adaptorului nerefacut din nivelurile lui', ' return j.verdict === v && JSON.stringify', ' return (j.verdict === v || true) && JSON.stringify', 'VALID cu integritatea nemasurata'],
['ordinea raspunsurilor lotului necitita', ' if (k >= 0) return items.map(', ' if (k >= 0 && false) return items.map(', 'raspunde in alta ordine'],
['un lot neterminat ia cu el toate verdictele (fara judecata pe rand)', ' if (items.length === 1) return [{ error: lot.motiv }];', ' if (items.length >= 1) return items.map(() => ({ error: lot.motiv }));', 'tine adaptorul pe loc'],
['listele pachetului inaintea celor ale contextului', "{ input[k] = [...v, ...input[k]]; note.stapled[k] = 'context+pack'; }", "{ input[k] = [...input[k], ...v]; note.stapled[k] = 'context+pack'; }", '64 de liste de rechemare'],
['constantele pietei (arbitrul) ale organizatiei', 'market: A, jobId: A, constants: V,', 'market: A, jobId: A, constants: A,', 'arbitrul pietei'],
['faptele reputatiei ale organizatiei', "'device-reputation': { facts: V,", "'device-reputation': { facts: A,", 'faptele reputatiei'],
['o cheie a modulului dat intreg scoasa din clasificare (constants)', 'market: A, jobId: A, constants: V,', 'market: A, jobId: A,', 'acoperire: fiecare cheie pe care adaptorul'],
['o cheie in plus a reputatiei aruncata in loc sa ajunga la modul', "facts: V, params: A, claimed: A, '*': A }", 'facts: V, params: A, claimed: A }', 'acoperire: fiecare cheie pe care adaptorul'],
['un fel care citeste lantul scos din lista', "export const CITESC_LANTUL = ['envelope', 'payment-receipt', 'market-timeline',", "export const CITESC_LANTUL = ['envelope', 'payment-receipt',", 'acoperire: felurile judecate citind lantul'],
['derivarea raportului PQ sarita', " if (dv.ok === false) V.pica(acc, 'integrity', 'pqreport.derivation', dv.reason);", " if (dv.ok === false && false) V.pica(acc, 'integrity', 'pqreport.derivation', dv.reason);", 'rezumatul rescris'],
['raportul PQ lasat in afara retelei', " if (!r.levels || r.artifact === 'shield-console') continue;", ' if (!r.levels || FELURI_PROPRII.includes(r.artifact)) continue;', 'un raport PQ al carui plic'],
['o masina numarata ca cerand --online', '(CITESC_LANTUL.includes(r.artifact) ? iesire.network.needed', '(CITESC_LANTUL.includes(r.artifact) || true ? iesire.network.needed', 'o masina a carei notarizare'],
['lantul ilizibil netrecut in rezumat', ' if (N.unmeasured.length) motive.push(', ' if (N.unmeasured.length && false) motive.push(', 'capat inchis'],
['finalitatea pe testnet nenumita', " iesire.network.finality.push({ id: r.id, chain: m ? Number(m[1]) : null, testnet: m ? !!m[2] : null });", " iesire.network.finality.push({ id: r.id, chain: m ? Number(m[1]) : null, testnet: false });", 'finalitatea citita isi numeste lantul'],
['Shield: executia nelegata de plan', ' if (st.execution && st.execution.chainOk && st.migration && st.migration.total !== null) {', ' if (st.execution && st.execution.chainOk && st.migration && st.migration.total !== null && false) {', 'Shield: o executie din care lipseste'],
['Shield: randul de sfarsit al executiei necitit', ' if (!(obiect(s) && s.total === facute.length', ' if (false && !(obiect(s) && s.total === facute.length', 'Shield: o executie al carei rand de sfarsit'],
['increderea adusa de organizatie lasata sa dea VALID', " if (v.verdict === 'VALID' && proprii.length) {", " if (v.verdict === 'VALID' && proprii.length && false) {", 'pachet fara context'],
['ceasul din pachet folosit', ' else note.dropped.push(k); // verifier-only si clock: o valoare din pachet nu se foloseste niciodata',
' else if (c === C) { input[k] = v; note.fromContext.push(k); } else note.dropped.push(k);', 'ceasul pachetului nu se foloseste'],
['increderea din pachet castiga peste cea a celui care verifica', ' const castigaContextul = (k) => Object.hasOwn(ctx, k);', ' const castigaContextul = (k) => false && Object.hasOwn(ctx, k);', 'atac: emitentii de incredere'],
['listele de stare ale contextului aruncate', '{ input[k] = [...v, ...input[k]];', '{ input[k] = [...input[k]];', 'o lista de stare adusa de cel care verifica'],
['contextul poate scrie artefactul', ' } else note.contextIgnored.push(k); // un context nu poate scrie artefactul organizatiei', ' } else { input[k] = v; }', 'un context nu poate scrie artefactul'],
['cheile KEM private citite din pachet', 'maxAgeS: V, statusLists: S, kem: O };', 'maxAgeS: V, statusLists: S, kem: V };', 'cheile KEM private'],
['verdictul scris de pachet folosit', " spune('pack.verdict', pack.verdict, verdict);", " if (typeof pack.verdict === 'string') iesire.summary.verdict = pack.verdict; spune('pack.verdict', pack.verdict, verdict);", 'verdictele scrise de pachet'],
['reteaua citita mereu (si fara --online)', 'return { file: f, online: !!online };', 'return { file: f, online: true };', 'fara --online'],
['artefactele care cer reteaua nenumite', " if (lantul.some((l) => l.state === 'NOT_MEASURED' && l.cause === 'claim-not-checked')) (CITESC_LANTUL",
" if (lantul.some((l) => l.state === 'NOT_MEASURED' && l.cause === 'claim-not-checked') && false) (CITESC_LANTUL", 'fara --online'],
['un fel necunoscut nu mai coboara rezumatul', " if (iesire.unjudged.length && verdict === 'VALID') {", " if (iesire.unjudged.length && verdict === 'VALID' && false) {", 'un fel pe care nu il judeca nimeni'],
['un id repetat judecat a doua oara', ' if (vazute.has(id)) { nm(', ' if (vazute.has(id) && false) { nm(', 'un id repetat'],
['Shield: lantul de audit rupt ignorat', ' if (!st.auditChain.ok) V.pica(', ' if (!st.auditChain.ok && false) V.pica(', 'Shield: o intrare a jurnalului schimbata'],
['Shield: plicul mincinos ignorat', ' if (st.envelopes.bad.length) V.pica(', ' if (st.envelopes.bad.length && false) V.pica(', 'Shield: lant refacut coerent'],
['Shield: chainOk mincinos ignorat', ' if (st.selfReportSuspect) V.pica(', ' if (st.selfReportSuspect && false) V.pica(', 'Shield: burafu declara chainOk:false'],
['Shield: lantul executiei rupt ignorat', ' if (st.execution && !st.execution.chainOk) V.pica(', ' if (st.execution && !st.execution.chainOk && false) V.pica(', 'stricat shield-console'],
['Shield: planul fara lista ignorat', ' if (st.migration && st.migration.total === null) V.pica(', ' if (st.migration && st.migration.total === null && false) V.pica(', 'Shield: un plan fara lista'],
['Shield: burafu gol acceptat', '&& Array.isArray(b.entries) && b.entries.length > 0)) {', '&& Array.isArray(b.entries) && b.entries.length >= 0)) {', 'Shield: un buraf fara intrari'],
['Shield: semnatura nejudecata trecuta sub tacere', " if (semnate.length) V.nemasurat(acc, 'authenticity', 'claim-not-checked'", " if (semnate.length && false) V.nemasurat(acc, 'authenticity', 'claim-not-checked'", 'Shield: o intrare care poarta o semnatura'],
['raportul PQ dezlegat de plic acceptat', " if (!leg.ok) V.pica(acc, 'integrity', 'pqreport.binding', leg.reason);", " if (!leg.ok && false) V.pica(acc, 'integrity', 'pqreport.binding', leg.reason);", 'stricat pq-compliance-report'],
['o cheie citita de adaptor scoasa din clasificare (trustedIssuers)', 'audience: V, nonce: V, trustedIssuers: V, maxAgeS: V,', 'audience: V, nonce: V, maxAgeS: V,', 'acoperire: fiecare cheie pe care adaptorul'],
['un fel al suitei fara domeniu (device-reputation)', "'device-operation-log': 'devices', 'device-reputation': 'devices',", "'device-operation-log': 'devices',", 'acoperire: fiecare fel al suitei'],
];
function ruleaza(modul, doar) {
return new Promise((gata) => {
const env = { ...process.env, AERE_CONFORMANCE_RPC_28001: INCHIS, AERE_CONFORMANCE_RPC_2800: INCHIS };
if (modul) env.AERE_ORG_MODUL = modul; else delete env.AERE_ORG_MODUL;
if (doar) env.AERE_ORG_DOAR = doar; else delete env.AERE_ORG_DOAR;
const c = spawn(process.execPath, [PROBA], { env, stdio: ['ignore', 'pipe', 'pipe'] }); let out = '';
const ceas = setTimeout(() => c.kill(), 600000);
c.stdout.on('data', (x) => { out += x; }); c.stderr.on('data', (x) => { out += x; });
c.on('close', (cod) => { clearTimeout(ceas); gata({ cod, rulat: /organizatie: \d+\/\d+ cum trebuia/.test(out), rosii: out.split('\n').filter((l) => l.includes('[RAU ]')), nemasurat: /^NEMASURAT/m.test(out), out }); });
});
}
const ramase = () => fs.readdirSync(AICI).filter((f) => /^_plantat-org-/.test(f));
let rele = 0;
const src = fs.readFileSync(SURSA, 'utf8');
if (ramase().length) { console.log(`STRICAT: copii plantate ramase dinainte: ${ramase().join(', ')}`); process.exit(2); }
const m = await ruleaza(null, null);
if (m.nemasurat) { console.log('NEMASURAT: proba nu poate rula aici'); process.exit(2); }
if (m.rulat && m.cod === 0 && !m.rosii.length) console.log(` OK martorul: proba intreaga verde pe organizatie.mjs neatins (${(m.out.match(/organizatie: (\d+\/\d+)/) || [])[1]})`);
else { rele++; console.log(` STRICAT martorul nu e verde (cod ${m.cod}, ${m.rosii.length} rosii): ${m.rosii.slice(0, 2).join(' | ')}`); }
const planteaza = async ([nume, din, inl, tinta], i) => {
const n = src.split(din).length - 1;
if (n !== 1) return [false, ` STRICAT ${nume}: tiparul apare de ${n} ori`];
const f = path.join(AICI, `_plantat-org-${process.pid}-${i}.mjs`);
fs.writeFileSync(f, src.replace(din, () => inl));
try {
const r = await ruleaza(f, tinta);
if (!r.rulat) return [false, ` STRICAT ${nume}: proba nu a ajuns la rezumat (cod ${r.cod}): ${r.out.trim().split('\n').slice(-1)[0].slice(0, 160)}`];
if (r.rosii.some((l) => l.includes(tinta))) return [true, ` ROSU cum trebuia ${nume} (randul '${tinta}' pica)`];
return [false, ` CONTROL CAZUT ${nume}: randul '${tinta}' a ramas verde`];
} finally { fs.rmSync(f, { force: true }); }
};
const rez = new Array(PLANTARI.length); let k = 0;
// cate doua probe deodata: fiecare porneste adaptorul suitei si verificatorul de referinta; laptopul e impartit
await Promise.all(Array.from({ length: 2 }, async () => { while (k < PLANTARI.length) { const i = k++; rez[i] = await planteaza(PLANTARI[i], i); } }));
for (const [bun, linie] of rez) { console.log(linie); if (!bun) rele++; }
if (ramase().length) { rele++; console.log(` STRICAT copii plantate ramase: ${ramase().join(', ')}`); }
console.log(rele ? `CONTROL NEGATIV: ${rele} probleme` : `DOVEDIT: martorul verde, ${PLANTARI.length} din ${PLANTARI.length} paznici scosi -> randul lor rosu`);
process.exitCode = rele ? 1 : 0;