// Controlul negativ al probelor agentilor (politica, registrul, aprobarea si revocarea, linia de comanda): fiecare paznic se strica intr-o COPIE a // dosarului, proba lui ruleaza pe copie si TREBUIE sa iasa rosie, cu probele chiar rulate (rezumatul lor exista); pe copia neatinsa, // verde. O plantare al carei tipar nu apare exact o data e un esec al controlului, nu o linie informativa. Trei stari: o proba care nu // ajunge la rezumat e STRICAT, si se numara esec (rosul ei nu masoara nimic). // 2026-09-29 (B-17): acopera si paznicii noi - argumentele in aprobare, hash-ul politicii recalculat, antedatarea (la scriere si fata // de ancore), ancora altei ramuri, sesiunea derivata, dovada de echivocare, reluarea registrului, campul necunoscut, activul, actionHash canonic. // node control-negativ-aprobare.mjs iesire 0 = martorii verzi si toate plantarile rosii // Proba politicii foloseste verificatorul AIP-23 (AERE_VERIFY_PROOF sau ../aere-proof-protocol/verify.mjs); fara el, martorul ei iese // cu 2 (partea AIP-23 NEMASURATA) si se accepta ca martor numai asa, cu zero RAU. import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { spawnSync } 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 P = { pol: 'proba-agent-policy.mjs', reg: 'proba-agent-ledger.mjs', apr: 'proba-agent-aprobare.mjs', cli: 'proba-agent-cli.mjs' }; const PLANTARI = [ // [nume, fisier, tipar, inlocuire, proba] ['nonce-ul unei aprobari nu mai e unic', 'agent-ledger.mjs', "if (ap && folosite.has(String(ap.nonce))) { respinse.push('nonce already used'); continue; }", '', P.apr], ['un aprobator nenumit in politica numara', 'agent-aprobare.mjs', 'if (!policy.approval.approvers.includes(humanId)) return', 'if (false) return', P.apr], ['semnatura aprobarii nu se mai verifica', 'agent-aprobare.mjs', "if (!sig) return { ok: false, error: 'the approval signature does not verify' };", '', P.apr], ['aprobarea devine scutire de limita', 'agent-policy.mjs', 'if (!d.allowed || !needsApproval(policy, action)) return d;', 'if (needsApproval(policy, action) && (ctx.approvers || []).length >= policy.approval.threshold) return { allowed: true, reason: "approved (exempt)" }; if (!d.allowed || !needsApproval(policy, action)) return d;', P.apr], ['verificatorul ignora revocarile date separat', 'agent-ledger.mjs', 'let revokedAt = ext.revokedAt;', 'let revokedAt = null;', P.apr], ['revocarea nu mai cere proprietarul', 'agent-aprobare.mjs', "if (humanIdFromKey(k) !== policy.owner) return { ok: false, error: 'the revocation is not signed by the owner named in the policy' };", '', P.apr], ['aprobarea nu mai e legata de continutul actiunii', 'agent-aprobare.mjs', 'if (ap.actionHash !== actionHash(action)) return', 'if (false) return', P.apr], ['argumentele uneltei nu mai intra in continutul aprobat', 'agent-aprobare.mjs', 'if (a.args !== undefined) c.argsHash = sha(canonical(a.args));', '', P.apr], ['verificatorul crede hash-ul dat in loc sa il recalculeze', 'agent-ledger.mjs', 'if (hashFixat != null && String(hashFixat).toLowerCase() !== policyHash) return', 'if (hashFixat != null) policyHash = String(hashFixat).toLowerCase(); if (false) return', P.reg], ['registrul accepta la scriere o intrare antedatata', 'agent-ledger.mjs', 'if (Number(at) < acum - TOLERANTA_S) throw', 'if (false) throw', P.reg], ['ancora nu mai margineste timpul de jos', 'agent-ledger.mjs', 'if (i > a.seq && atI < a.at - tol) return', 'if (false) return', P.reg], ['ancora nu mai trebuie sa numeasca o intrare a registrului', 'agent-ledger.mjs', 'if (!ledger.entries[s] || ledger.entries[s].hash !== a.hash) return', 'if (false) return', P.reg], ['verificatorul nu mai cere sesiunea registrului in intrare', 'agent-ledger.mjs', ' || b.session !== ledger.session) return', ') return', P.reg], ['sesiunea registrului nu mai trebuie sa fie cea derivata', 'agent-ledger.mjs', 'if (ledger.session !== sessionId(ledger.agentId, policyHash)) return', 'if (false) return', P.reg], ['dovada de echivocare fara semnaturile agentului', 'agent-ledger.mjs', "if (!intrareSemnata(e, pub)) return { ok: false, error: 'an entry is not signed by the agent' };", '', P.reg], ['un registru atins se poate relua', 'agent-ledger.mjs', 'if (!v.ok) throw new Error(`agent-ledger: the ledger to resume does not verify', 'if (false) throw new Error(`agent-ledger: the ledger to resume does not verify', P.reg], ['reluarea uita nonce-urile folosite', 'agent-ledger.mjs', 'for (const e of entries) for (const n of nonceuri(e.body.approvals)) folosite.add(n);', '', P.apr], ['reluarea uita revocarea', 'agent-ledger.mjs', 'JSON.parse(JSON.stringify(ledger.entries)), v.revocations.revokedAt);', 'JSON.parse(JSON.stringify(ledger.entries)), null);', P.apr], ['linia de comanda suprascrie o cheie existenta', 'agent-cli.mjs', 'if (fs.existsSync(cheie)) throw new Folosire(', 'if (false) throw new Folosire(', P.cli], ['linia de comanda lasa pe oricine sa aprobe', 'agent-cli.mjs', 'if (!policy.approval || !policy.approval.approvers.includes(human.humanId)) throw', 'if (false) throw', P.cli], ['verify din linia de comanda uita hash-ul numit in fisierul politicii', 'agent-cli.mjs', "const pinned = get('--policy-hash') ?? j.policyHash;", "const pinned = get('--policy-hash');", P.cli], ['record deschide mereu un registru nou in loc sa il reia', 'agent-cli.mjs', 'const L = fs.existsSync(lf) ? resumeLedger(', 'const L = false ? resumeLedger(', P.cli], ['politica cu un camp necunoscut e primita', 'agent-policy.mjs', 'if (necunoscute.length) throw', 'if (false) throw', P.pol], ['o plata in alt activ trece pe langa limita', 'agent-policy.mjs', 'if (action.asset != null && String(action.asset) !== policy.spend.asset) return', 'if (false) return', P.pol], ['actionHash-ul plicului nu mai e canonic', 'agent-policy.mjs', "actionHash: sha256(Buffer.from(canonical(action), 'utf8')),", "actionHash: sha256(Buffer.from(JSON.stringify(action), 'utf8')),", P.pol], ]; const FISIERE = ['agent-policy.mjs', 'agent-ledger.mjs', 'agent-aprobare.mjs', 'agent-cli.mjs', P.pol, P.reg, P.apr, P.cli]; function copie() { const t = fs.mkdtempSync(path.join(os.tmpdir(), 'aere-b2-ctl-')); for (const f of FISIERE) fs.copyFileSync(path.join(AICI, f), path.join(t, f)); return t; } function ruleaza(t, proba) { const env = { ...process.env }; if (VERIFY) env.AERE_VERIFY_PROOF = VERIFY; else delete env.AERE_VERIFY_PROOF; const r = spawnSync(process.execPath, [path.join(t, proba)], { encoding: 'utf8', timeout: 240000, env }); const out = (r.stdout || '') + (r.stderr || ''); const m = /agent-(policy|ledger|aprobare|cli): (\d+)\/(\d+)/.exec(out); return { cod: r.status, rulat: !!m, rele: (out.match(/^\s*(RAU\s|\[RAU)/gm) || []).length }; } let esecuri = 0; for (const proba of Object.values(P)) { const t0 = copie(); const m0 = ruleaza(t0, proba); fs.rmSync(t0, { recursive: true, force: true }); const verde = m0.rulat && m0.rele === 0 && (m0.cod === 0 || (m0.cod === 2 && proba === P.pol && !VERIFY)); if (verde) console.log(` OK martorul ${proba}: copia neatinsa verde${m0.cod === 2 ? ' (fara verificatorul AIP-23: partea lui NEMASURATA)' : ''}`); else { esecuri++; console.log(` RAU martorul ${proba} nu e verde (cod ${m0.cod}, ${m0.rulat ? m0.rele + ' RAU' : 'nu a ajuns la rezumat'})`); } } for (const [nume, f, din, inl, proba] of PLANTARI) { const t = copie(); const fp = path.join(t, f); const src = fs.readFileSync(fp, 'utf8'); if (src.split(din).length !== 2) { esecuri++; console.log(` RAU ${nume}: tiparul nu apare exact o data in ${f}`); fs.rmSync(t, { recursive: true, force: true }); continue; } fs.writeFileSync(fp, src.replace(din, inl)); const r = ruleaza(t, proba); fs.rmSync(t, { recursive: true, force: true }); if (r.rulat && r.cod !== 0 && r.rele > 0) console.log(` OK ${nume}: ${proba} ROSIE (${r.rele} RAU)`); else { esecuri++; console.log(` RAU ${nume}: ${r.rulat ? `${proba} a ramas verde` : `${proba} nu a ajuns la rezumat (STRICAT)`} (cod ${r.cod})`); } } console.log(esecuri ? `RAU: ${esecuri} esecuri ale controlului` : `DOVEDIT: martorii verzi, ${PLANTARI.length} din ${PLANTARI.length} plantari rosii`); process.exitCode = esecuri ? 1 : 0;