// Controlul negativ al probei vederii organizatiei in browser (proba-organizatie-web.mjs): fiecare defect se planteaza intr-o COPIE a paginii, // proba ruleaza pe copie (primeste calea ei) si randul NUMIT trebuie sa iasa rosu, cu proba chiar rulata pana la rezumat; 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-organizatie-web.mjs iesire 0 = martorul verde si toate plantarile rosii pe randul 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 PAGINA = path.join(AICI, 'consola-web', 'index.html'); const PLANTARI = [ // [nume, tipar, inlocuire, randul probei (o parte din numele lui)] ['un domeniu neprezentat in culoarea buna', 'NOT_PRESENTED: "dim"', 'NOT_PRESENTED: "ok"', 'domeniul neprezentat aratat NOT PRESENTED'], ['un domeniu neprezentat numarat la "Domains presented"', 'const neprez = doms.filter((d) => aratatDom.get(d) === "NOT_PRESENTED");', 'const neprez = doms.filter((d) => false);', 'domeniul neprezentat aratat NOT PRESENTED'], ['INVALID in culoarea buna', 'INVALID: "bad", UNCHECKED: "bad" };', 'INVALID: "ok", UNCHECKED: "bad" };', 'rezumatul INVALID in culoarea rea'], ['regula refuzata nenumita pe artefact', 'if (Array.isArray(r.failed) && r.failed.length) w.append(el("div","arules","refused by "+r.failed.join(", ")));', 'if (Array.isArray(r.failed) && r.failed.length && false) w.append(el("div","arules","refused by "+r.failed.join(", ")));', 'rezumatul INVALID in culoarea rea'], ['amprenta dovezii prescurtata', 'el("span","hval",r.inputSha256||"—")', 'el("span","hval",short(r.inputSha256))', 'amprenta intreaga a dovezii'], // (revizia B2) antetul ia VALID in loc de rezumat: corectia il coboara la domenii, dar numeste o iesire reala contradictorie ['verdictul din antet luat VALID, nu din rezumat', 'let verdict = pachet ? "UNCHECKED" : String(s.verdict || "?");', 'let verdict = pachet ? "UNCHECKED" : "VALID";', 'o iesire reala nu e numita contradictorie'], ['culoarea casetei de domeniu din cel mai bun artefact', 'h.append(el("span","pill "+pill(dv),textVerdict(dv)));', 'h.append(el("span","pill "+(arts.some((x)=>x.domain===d.domain&&x.verdict==="VALID")?"ok":pill(dv)),textVerdict(dv)));', 'cate o caseta pe domeniu'], // revizia B2 (2026-10-21): paznicii noi ai vederii ['antetul necoborat la cel mai slab domeniu cerut (o iesire editata crezuta)', ' let v = slabV([verdict, ...din]);', ' let v = verdict;', 'rezumatul VALID peste un domeniu cerut INVALID'], ['caseta de domeniu necoborata la cel mai slab artefact', 'const v = ale.length ? slabV([String(d.verdict), ...ale.map((x) => String(x.verdict))]) : "NOT_PRESENTED";', 'const v = ale.length ? String(d.verdict) : "NOT_PRESENTED";', 'domeniul identity VALID peste un artefact INVALID'], ['caseta retelei verde peste un lant necitit', 'const reteaBuna = !!net.online && !retea.length;', 'const reteaBuna = !!net.online;', 'caseta retelei'], ['finalitatea pe testnet nespusa in caseta retelei', ' if (pePlasa.length) retea.push(', ' if (pePlasa.length && false) retea.push(', 'caseta retelei'], ['textul din pachet pus ca HTML', 'if(x!=null)n.textContent=x;return n;}', 'if(x!=null)n.innerHTML=x;return n;}', 'un marcaj adus de pachet'], ['alarmele fara rupere de rand', 'color:var(--crit);border-radius:10px;padding:11px 13px;font-size:12.5px;overflow-wrap:anywhere}', 'color:var(--crit);border-radius:10px;padding:11px 13px;font-size:12.5px}', 'text lung fara spatii'], ['numele organizatiei fara rupere de rand', '.host .mono{color:var(--ink);overflow-wrap:anywhere;min-width:0}', '.host .mono{color:var(--ink)}', 'text lung fara spatii'], ['un pachet brut aratat ca judecata', 'const pachet = o.kind === "aere-organization-evidence-pack";', 'const pachet = false && o.kind === "aere-organization-evidence-pack";', 'un pachet brut lipit e UNCHECKED'], ['verdictul scris de pachet ascuns', 'for (const x of (o.selfReport && o.selfReport.suspect) || []) A.append(', 'for (const x of []) A.append(', 'verdictul scris de pachet e aratat ca suspect'], ['sectiunile consolei lasate vizibile peste domenii', 'for (const id of ["sec-chain","sec-ladder","sec-mig","lead-console"]) document.getElementById(id).hidden = !on;', 'for (const id of ["sec-chain","sec-ladder","sec-mig","lead-console"]) document.getElementById(id).hidden = false;', 'sectiunile consolei ascunse'], ['domeniile ramase dupa intoarcerea la consola', 'for (const id of ["orgsec","lead-org"]) document.getElementById(id).hidden = on;', 'for (const id of ["orgsec","lead-org"]) document.getElementById(id).hidden = false;', 'o stare a consolei dupa o judecata'], ['un id de artefact mai lat decat telefonul', '.aid{font-family:var(--mono);font-size:12px;font-weight:600;overflow-wrap:anywhere;min-width:0}', '.aid{font-family:var(--mono);font-size:12px;font-weight:600;white-space:nowrap;min-width:600px}', '390px: judecata buna: pagina cat ecranul'], // o eroare la redare e prinsa de butonul Render si scrisa in campul de eroare (nu e o eroare de pagina): o prinde randul campului de eroare ['o eroare de script in vederea organizatiei', ' consoleMode(false);\n const pachet', ' consoleMode(false); nuExistaFunctia();\n const pachet', 'nicio iesire reala nu a dat un mesaj de eroare la redare'], ]; function ruleaza(pagina) { return new Promise((resolve) => { const c = spawn(process.execPath, [path.join(AICI, 'proba-organizatie-web.mjs'), pagina]); let out = ''; const ceas = setTimeout(() => c.kill(), 300000); c.stdout.on('data', (x) => { out += x; }); c.stderr.on('data', (x) => { out += x; }); c.on('close', (cod) => { clearTimeout(ceas); resolve({ cod, rulat: /organizatie-web: \d+\/\d+/.test(out), rosii: out.split('\n').filter((l) => l.includes('[RAU ]')), nemasurat: /^NEMASURAT/m.test(out) }); }); }); } const T = fs.mkdtempSync(path.join(os.tmpdir(), 'org-web-ctl-')); let rele = 0; try { // capetele de rand la LF inainte de orice (o copie de pe Windows poate avea CRLF), iar martorul e scris din ACEEASI forma ca plantarile const src = fs.readFileSync(PAGINA, 'utf8').replace(/\r\n/g, '\n'); const m0 = path.join(T, 'martor.html'); fs.writeFileSync(m0, src); const m = await ruleaza(m0); if (m.nemasurat) { console.log('NEMASURAT: proba nu poate rula aici (fara browser)'); process.exit(2); } if (m.rulat && m.cod === 0 && !m.rosii.length) console.log(' OK martorul: copia neatinsa verde'); else { rele++; console.log(` STRICAT martorul nu e verde (cod ${m.cod}, ${m.rosii.length} rosii)`); } const planteaza = async ([nume, din, inl, tinta], i) => { if (src.split(din).length !== 2) return [false, ` STRICAT ${nume}: tiparul apare de ${src.split(din).length - 1} ori`]; const f = path.join(T, `p${i}.html`); fs.writeFileSync(f, src.replace(din, () => inl)); const r = await ruleaza(f); if (!r.rulat) return [false, ` STRICAT ${nume}: proba nu a ajuns la rezumat (cod ${r.cod})`]; if (r.rosii.some((l) => l.includes(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)`]; }; // cate doua browsere deodata (fiecare cateva sute de MB, plus judecatile reale pe care le face proba) const rez = new Array(PLANTARI.length); let k = 0; 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++; } } finally { fs.rmSync(T, { recursive: true, force: true }); } console.log(rele ? `CONTROL NEGATIV: ${rele} probleme` : `DOVEDIT: martorul verde, ${PLANTARI.length} din ${PLANTARI.length} defecte plantate -> proba lor rosie`); process.exitCode = rele ? 1 : 0;