aere-quantum/identity/control-negativ-conformitate.mjs

66 lines
5.9 KiB
JavaScript

// Controlul negativ al conformitatii (conformitate.mjs, proba-conformitate.mjs): fiecare paznic scos intr-o COPIE trebuie sa
// inroseasca proba NUMITA, cu proba chiar rulata; pe copia neatinsa, verde. Trei stari: un tipar care nu apare exact o data sau o
// proba care nu ajunge la rezumat e STRICAT si se numara esec.
// node control-negativ-conformitate.mjs iesire 0 = martorul verde si toate plantarile rosii pe proba lor
import fs from 'node:fs'; import os from 'node:os'; 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 DEV_VERIFY = path.resolve(AICI, '..', 'aere-proof-protocol', 'verify.mjs');
const VERIFY = process.env.AERE_VERIFY_PROOF || (fs.existsSync(DEV_VERIFY) ? DEV_VERIFY : '');
const C = 'conformitate.mjs';
const PLANTARI = [
// [nume, tipar, inlocuire, proba (inceputul numelui ei)]
['equals nu mai compara', "if (Object.hasOwn(r, 'equals')) return canonical(v) === canonical(r.equals);", "if (Object.hasOwn(r, 'equals')) return true;", 'neconform: jurisdictie interzisa'],
['notIn nu mai compara', "if (Object.hasOwn(r, 'notIn')) return !r.notIn.some((x) => canonical(x) === canonical(v));", "if (Object.hasOwn(r, 'notIn')) return true;", 'neconform: jurisdictie interzisa'],
['atLeast nu mai compara', "if (Object.hasOwn(r, 'atLeast')) return typeof v === 'number' && Number.isFinite(v) && v >= r.atLeast;", "if (Object.hasOwn(r, 'atLeast')) return true;", 'neconform: jurisdictie interzisa'],
['o afirmatie ceruta si nearatata trece', 'if (!are) return false;', 'if (!are) return true;', 'neconform: o afirmatie ceruta nearatata'],
['starea nejudecata trece drept nerevocata', 'if (policy.requireStatus && !(status && status.pass === true))', 'if (false)', 'neconform: starea ceruta'],
['o prezentare invalida judecata conforma', 'if (!v.valid) motive.push(', 'if (false) motive.push(', 'neconform: emitent in afara'],
['emitentii politicii nu mai ajung la verificare', 'trustedIssuers: policy.trustedIssuers,', 'trustedIssuers: null,', 'neconform: emitent in afara'],
['judecata fara publicul si nonce-ul verificatorului', "if (typeof audience !== 'string' || !audience || typeof nonce !== 'string' || !nonce) throw new Error('compliance: the verifier", "if (false) throw new Error('compliance: the verifier", 'neconform: prezentare facuta pentru alt verificator'],
['regulile nu mai sunt in forma normala', '}).sort((a, b) => (canonical(a) < canonical(b) ? -1 : 1));', '});', 'politica: forma normala'],
['campuri necunoscute primite in politica', 'if (necunoscute.length) throw', 'if (false) throw', 'CONTROL: politica refuza'],
['id-ul detinatorului scris in inregistrare', 'subject: pseudonim,', 'subject: rez.holder,', 'inregistrarea (plic AIP-23 compliance) NU poarta date personale'],
['afirmatiile intoarse si pentru o judecata neconforma', '...(keepClaims && !motive.length ? { claims } : {})', '...(keepClaims ? { claims } : {})', 'rezultatul nu poarta afirmatiile'],
['cheia verificatorului ignorata la pseudonim', '(pseudonymKey ? crypto.createHmac(', '(false ? crypto.createHmac(', 'pseudonimul'],
];
const FISIERE = ['identity.mjs', 'identity-cli.mjs', C, 'proba-conformitate.mjs'];
function copie() {
const t = fs.mkdtempSync(path.join(os.tmpdir(), 'aere-conf-ctl-'));
fs.mkdirSync(path.join(t, 'aere-identity')); fs.mkdirSync(path.join(t, 'proof-kinds'));
for (const f of FISIERE) fs.copyFileSync(path.join(AICI, f), path.join(t, 'aere-identity', f));
fs.copyFileSync(path.join(AICI, '..', 'proof-kinds', 'proof-kinds.mjs'), path.join(t, 'proof-kinds', 'proof-kinds.mjs'));
return t;
}
function ruleaza(t) {
const env = { ...process.env }; if (VERIFY) env.AERE_VERIFY_PROOF = VERIFY; else delete env.AERE_VERIFY_PROOF;
return new Promise((resolve) => {
const c = spawn(process.execPath, [path.join(t, 'aere-identity', 'proba-conformitate.mjs')], { env }); let out = '';
const ceas = setTimeout(() => c.kill(), 180000);
c.stdout.on('data', (x) => { out += x; }); c.stderr.on('data', (x) => { out += x; });
c.on('close', (cod) => { clearTimeout(ceas); resolve({ cod, rulat: /aere-compliance: \d+\/\d+/.test(out), rosii: out.split('\n').filter((l) => l.startsWith(' RAU ')) }); });
});
}
async function planteaza([nume, din, inl, tinta]) {
const t = copie();
try {
const f = path.join(t, 'aere-identity', C); const src = fs.readFileSync(f, 'utf8');
if (src.split(din).length !== 2) return [false, ` STRICAT ${nume}: tiparul apare de ${src.split(din).length - 1} ori`];
fs.writeFileSync(f, src.replace(din, inl));
const r = await ruleaza(t);
if (!r.rulat) return [false, ` STRICAT ${nume}: proba nu a ajuns la rezumat (cod ${r.cod})`];
if (r.rosii.some((l) => l.startsWith(' RAU ' + tinta))) return [true, ` ROSU cum trebuia ${nume} (proba '${tinta}' pica)`];
return [false, ` CONTROL CAZUT ${nume}: proba '${tinta}' a ramas verde (${r.rosii.length} rosii altundeva)`];
} finally { fs.rmSync(t, { recursive: true, force: true }); }
}
let rele = 0;
const t0 = copie(); const m = await ruleaza(t0); fs.rmSync(t0, { recursive: true, force: true });
if (m.rulat && !m.rosii.length && (m.cod === 0 || (m.cod === 2 && !VERIFY))) console.log(' OK martorul: copia neatinsa verde' + (m.cod === 2 ? ' (plicul AIP-23 NEMASURAT: fara verificator)' : ''));
else { rele++; console.log(` STRICAT martorul nu e verde (cod ${m.cod}, ${m.rosii.length} rosii)`); }
const rez = new Array(PLANTARI.length); let i = 0;
await Promise.all(Array.from({ length: 4 }, async () => { while (i < PLANTARI.length) { const k = i++; rez[k] = await planteaza(PLANTARI[k]); } }));
for (const [bun, linie] of rez) { console.log(linie); if (!bun) rele++; }
console.log(rele ? `CONTROL NEGATIV: ${rele} probleme` : `DOVEDIT: martorul verde, ${PLANTARI.length} din ${PLANTARI.length} paznici scosi -> proba lor rosie`);
process.exitCode = rele ? 1 : 0;