diff --git a/README.md b/README.md index 4ea3f08..cf3f23c 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ test, counts as a failure of the control. Results measured on 2026-09-29 (Node.j | proof-kinds | 28/28 on 2026-10-18 with the same verifier (`AERE_VERIFY_PROOF=... node proba-proof-kinds.mjs`: fifteen kinds, the allowed values of the `secret-access` fields included) | seven negative controls inside the test | | readiness | 6/6 (`node proba-adrese-private.mjs`: the private-address rules, and a local listener no scan may touch) | the rate limit and the queue bound are tested where the service runs, not here (its README says so) | | control-plane | planner 44/44 (2026-10-18: a key agreement or a client-side TLS configured by the application itself is not routed to the TLS gateway; a self-signed trust anchor is blocked, not "automatic through PKI"; test code is LOW with its own scope), command line 10/10, execution 30/30 on real products started locally, remediation 33/33 on real TLS servers (all five server profiles measured end to end on 2026-10-18: nginx, Apache, HAProxy, Node, Go), compliance report 30/30 (with the AIP-23 verifier; test-code findings are counted apart and are not "exposed today"), console 8/8; the console viewer in a real Chromium, phone and desktop, 26/26 (`node proba-consola-web.mjs`, measured 2026-09-30; needs `playwright-core` and a Chromium, otherwise it exits 2) | remediation 7/7, compliance report 3/3 in this repository; viewer 8/8 (`node control-negativ-consola-web.mjs`) | -| identity | 52/52 (`node proba-identity.mjs`, a presentation optionally signed for one exact request (`request`) included, with the AIP-23 verifier for its envelope test; without it that test is reported as skipped and the exit code is 2), compliance 18/18 (`node proba-conformitate.mjs`), Travel Rule 20/20 (`node proba-travel-rule.mjs`; 2026-10-18: a missing originator id or nonce is a refusal, found when the verifier was enrolled in the conformance suite), SD-JWT 25/25 (`node proba-sdjwt.mjs`, the RFC 9901 vectors and fixtures derived from @sd-jwt/core 0.23.0 included), SD-JWT VC 10/10 (`node proba-sdjwt-vc.mjs`); interoperability with @sd-jwt/core and jose in both directions 26/26 and 28/28 (`interop/`, with those libraries installed in a folder you name; otherwise reported unmeasured), measured 2026-10-18 | 57/57 (`node control-negativ-identity.mjs`); compliance 17/17 (`node control-negativ-conformitate.mjs`); Travel Rule 20/20 (`node control-negativ-travel-rule.mjs`); SD-JWT 31/31 (`node control-negativ-sdjwt.mjs`); SD-JWT VC 16/16 (`node control-negativ-sdjwt-vc.mjs`) | +| identity | 52/52 (`node proba-identity.mjs`, a presentation optionally signed for one exact request (`request`) included, with the AIP-23 verifier for its envelope test; without it that test is reported as skipped and the exit code is 2), compliance 18/18 (`node proba-conformitate.mjs`) and Travel Rule 20/20 (`node proba-travel-rule.mjs`) with the same verifier (without it each reports one test unmeasured and exits 2; 2026-10-18: a missing originator id or nonce is a refusal, found when the verifier was enrolled in the conformance suite), SD-JWT 25/25 (`node proba-sdjwt.mjs`, the RFC 9901 vectors and fixtures derived from @sd-jwt/core 0.23.0 included), SD-JWT VC 10/10 (`node proba-sdjwt-vc.mjs`); interoperability with @sd-jwt/core and jose in both directions 26/26 and 28/28 (`interop/`, with those libraries installed in a folder you name; otherwise reported unmeasured), measured 2026-10-18 | 57/57 (`node control-negativ-identity.mjs`); compliance 17/17 (`node control-negativ-conformitate.mjs`); Travel Rule 20/20 (`node control-negativ-travel-rule.mjs`); SD-JWT 31/31 (`node control-negativ-sdjwt.mjs`); SD-JWT VC 16/16 (`node control-negativ-sdjwt-vc.mjs`) | | agents | policy 27/27 with the AIP-23 verifier (without it 25 run, 2 are reported as skipped and the exit code is 2), ledger 54/54 on 2026-10-05, approval and revocation 39/39, the chain as witness 26/26 without a network and 7/7 on testnet 28001 on 2026-09-30 (`proba-agent-ancora-testnet.mjs`, needs a funded testnet key and the AIP-23 verifier), command line 23/23 through files and processes only (on Linux and macOS one more test checks the key file mode; not measured here); x402 wallet 25/25, 2-of-2 co-signing 16/16 and payment verifier 14/14 without a network; on the public testnet 28001, 9/9 with the wallet key and 13/13 with the 2-of-2 contract wallet (`agents/x402/proba-x402-testnet.mjs`, `agents/x402/proba-cosign-testnet.mjs`, each needs a funded testnet key); the contract's artifact recompiles byte for byte with solc 0.8.23 (`node x402/recompileaza-contract.mjs --solc `) | 26/26 (`node control-negativ-aprobare.mjs`); the chain as witness 11/11 (`node control-negativ-ancora.mjs`); x402 30/30 (`node x402/control-negativ-wallet.mjs`); the contract's own tests (7) and their negative control (4/4) run in the Aere Network contracts project, not in this repository | | proof-of-ai | 6/6 with the AIP-23 verifier (`AERE_VERIFY_PROOF=... node proba-proof-of-ai.mjs`); without it the probe reports NEMASURAT and exits 2 | one negative control inside the test (an envelope touched after its hash: INVALID) | | payments | 23/23 without a chain (`node proba-risc.mjs`: the verdicts under a policy, the reproducible verdict hash, a receipt verified, nine forged ones refused by name, a malformed payment refused by name); 9/9 on testnet 28001 on 2026-10-02 (`AERE_TESTNET_KEY_FILE=... AERE_ETHERS_DIR=... node proba-plata-28001.mjs`: a payment allowed, paid, its receipt notarized and read back with finality PASSED, the public reader VALID; a payment above the limit refused with nothing sent; the fourth in the window refused; a forged receipt and a loosened policy INVALID) | 10/10 (`node proba-risc.mjs --control-negativ`: form, asset, counterparty, rate, per-payment limit, window, linkage, USD arithmetic, verdict reproduction, chain facts, each planted out on a copy and each forged fixture then accepted) | diff --git a/conformance/README.md b/conformance/README.md index 1fe462a..1ddccfd 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -237,6 +237,12 @@ a verdict. `node proba-conformance.mjs --control-negativ` (offline) gives 319 ro vectors need the testnet): 237 of 240 rules proven load-bearing, `identity.request` among them (planted out, exactly its 2 vectors fail). Before the change, the same commands on the untouched tree: 12 green, 0 red, 1 not measured; 318 green, 0 red, 3 not measured (236 of 239). Not run after the change: `--online`. +Run online later the same evening (21:06-21:25 UTC), with the reference verifier as served at aere.network/tools (fetched and installed +in an empty folder) and testnet 28001 read: `node proba-conformance.mjs --online` gives 12 rows green, 0 red; the published verifiers +pass 626 of 626 vectors, the independent Python implementation passes the 65 it claims and reports the other 561 not covered, 101,833 +malformed inputs and 183 malformed envelope files each got a verdict. `node proba-conformance.mjs --control-negativ --online` gives 322 +rows green, 0 red: 240 of 240 rules proven load-bearing through their vectors; the other 82 rows are the conditions of the device +verifier and the controls of the instruments. Measured again on 2026-10-18 (UTC), later the same day, after the AIP-23 kind `secret-access` (the audit entry of the secrets service, `pq-secrets/`) was added to proof-kinds and its three envelope vectors derived (Node.js 24.14.1, the reference verifier of the diff --git a/identity/README.md b/identity/README.md index 44620c6..70a9003 100644 --- a/identity/README.md +++ b/identity/README.md @@ -360,8 +360,8 @@ node proba-identity.mjs # 52: the paths above, each attack of the a node control-negativ-identity.mjs # on a copy, each of 57 guards removed -> its own named test turns red node proba-conformitate.mjs # 18: compliance policies judged on real presentations, the record without personal data, the command line node control-negativ-conformitate.mjs # on a copy, each of 17 guards removed -> its own named test turns red -node proba-travel-rule.mjs # 19: two VASPs with registry credentials, the whole exchange, and each attack of the review -node control-negativ-travel-rule.mjs # on a copy, each of 19 guards removed -> its own named test turns red +node proba-travel-rule.mjs # 20: two VASPs with registry credentials, the whole exchange, and each attack of the review +node control-negativ-travel-rule.mjs # on a copy, each of 20 guards removed -> its own named test turns red node proba-sdjwt.mjs # 25: the RFC 9901 vectors, SD-JWTs issued with AERE keys (EdDSA and ML-DSA-65), each attack, the fixtures of @sd-jwt/core node control-negativ-sdjwt.mjs # on a copy, each of 31 guards removed -> its own named test turns red node proba-sdjwt-vc.mjs # 10: the SD-JWT VC profile, the status list, the fixtures of @sd-jwt/sd-jwt-vc and @owf/token-status-list, the command line diff --git a/pq-secrets/test/control-negativ-secrete.mjs b/pq-secrets/test/control-negativ-secrete.mjs index d3e5c8d..d05f984 100644 --- a/pq-secrets/test/control-negativ-secrete.mjs +++ b/pq-secrets/test/control-negativ-secrete.mjs @@ -25,10 +25,26 @@ import { spawn } from 'node:child_process'; import { fileURLToPath } from 'node:url'; const HERE = path.dirname(fileURLToPath(import.meta.url)); -const RADACINA = path.resolve(HERE, '..', '..', '..'); // aerenew/ -const S = 'cloud-gateway/pq-secrets/secrete.mjs', SV = 'cloud-gateway/pq-secrets/server.mjs', PR = 'cloud-gateway/pq-secrets/test/proba-secrete.mjs'; -const IDN = 'tools/aere-identity/identity.mjs', CFM = 'tools/aere-identity/conformitate.mjs', PKS = 'tools/proof-kinds/proof-kinds.mjs'; -const FISIERE = [S, SV, PR, 'cloud-gateway/pq-kms/kms.mjs', 'cloud-gateway/pq-kms/server.mjs', 'cloud-gateway/pq-kms/hsm-radacina.mjs', IDN, CFM, PKS, 'tools/aere-verify-layer/sidecar.mjs']; +// Doua asezari, ca in secrete.mjs: depozitul de dezvoltare (aerenew/cloud-gateway/pq-secrets, tools/aere-identity, tools/proof-kinds, +// tools/aere-verify-layer) si forma publicata (pq-secrets/ langa pq-kms/, identity/, proof-kinds/, verify-layer/). Asezarea se alege dupa +// ce exista pe disc; daca niciuna nu e intreaga, controlul refuza sa porneasca si spune ce lipseste (nu un ENOENT din mijlocul lui). +const ASEZARI = { + dezvoltare: { radacina: path.resolve(HERE, '..', '..', '..'), sec: 'cloud-gateway/pq-secrets', kms: 'cloud-gateway/pq-kms', id: 'tools/aere-identity', pk: 'tools/proof-kinds', vl: 'tools/aere-verify-layer' }, + publicata: { radacina: path.resolve(HERE, '..', '..'), sec: 'pq-secrets', kms: 'pq-kms', id: 'identity', pk: 'proof-kinds', vl: 'verify-layer' }, +}; +const fisiereDin = (a) => [`${a.sec}/secrete.mjs`, `${a.sec}/server.mjs`, `${a.sec}/test/proba-secrete.mjs`, `${a.kms}/kms.mjs`, `${a.kms}/server.mjs`, + `${a.kms}/hsm-radacina.mjs`, `${a.id}/identity.mjs`, `${a.id}/conformitate.mjs`, `${a.pk}/proof-kinds.mjs`, `${a.vl}/sidecar.mjs`]; +const intreaga = (a) => fisiereDin(a).every((f) => fs.existsSync(path.join(a.radacina, f))); +const ASEZARE_NUME = intreaga(ASEZARI.dezvoltare) ? 'dezvoltare' : intreaga(ASEZARI.publicata) ? 'publicata' : null; +if (!ASEZARE_NUME) { + for (const [n, a] of Object.entries(ASEZARI)) console.log(`asezarea ${n}: lipsesc ${fisiereDin(a).filter((f) => !fs.existsSync(path.join(a.radacina, f))).join(', ')}`); + console.log('NEMASURAT: componentele surori nu sunt nici in forma publicata, nici in depozitul de dezvoltare'); + process.exit(2); +} +const ASEZARE = ASEZARI[ASEZARE_NUME]; +const RADACINA = ASEZARE.radacina; +const FISIERE = fisiereDin(ASEZARE); +const [S, SV, PR, , , , IDN, CFM, PKS] = FISIERE; const DEV_VERIFY = path.join(RADACINA, 'tools', 'aere-proof-protocol', 'verify.mjs'); const VERIFY = process.env.AERE_VERIFY_PROOF ? path.resolve(process.env.AERE_VERIFY_PROOF) : (fs.existsSync(DEV_VERIFY) ? DEV_VERIFY : ''); const NICIODATA = "process.env.AERE_SECRETS_PLANTA_NICIODATA === 'da'"; @@ -206,7 +222,7 @@ function ruleaza(dest) { const env = { ...envCurat(), AERE_SECRETS_PROBA_JSON: out }; if (VERIFY) env.AERE_VERIFY_PROOF = VERIFY; else delete env.AERE_VERIFY_PROOF; return new Promise((gata) => { - const c = spawn(process.execPath, [path.join(dest, PR)], { cwd: path.join(dest, 'cloud-gateway', 'pq-secrets'), env, stdio: ['ignore', 'ignore', 'pipe'] }); + const c = spawn(process.execPath, [path.join(dest, PR)], { cwd: path.join(dest, ASEZARE.sec), env, stdio: ['ignore', 'ignore', 'pipe'] }); let stderr = ''; c.stderr.on('data', (d) => { stderr = (stderr + d).slice(-4000); }); const ceas = setTimeout(() => c.kill(), 600000); c.on('close', (status, signal) => { @@ -249,6 +265,7 @@ async function main() { if (process.argv.includes('--ancore')) { let rele = 0; for (const p of PL) { const n = fs.readFileSync(path.join(RADACINA, p.fisier), 'utf8').split(p.ancora).length - 1; if (n !== 1) rele++; console.log(`${n === 1 ? 'OK ' : 'RAU '} ${p.id} ancora de ${n} ori in ${p.fisier}`); } return rele ? 1 : 0; } if (new Set(PL.map((p) => p.id)).size !== PL.length) throw new Error('doua plantari cu acelasi id'); if (autoproba) console.log('AUTOPROBA: momelile de mai jos TREBUIE sa primeasca verdictul lor de esec\n'); + console.log(`asezarea: ${ASEZARE_NUME} (${FISIERE.length} fisiere copiate in fiecare copie)`); if (!VERIFY) console.log('verificatorul AIP-23 lipseste (AERE_VERIFY_PROOF): proba plicurilor va fi SARITA in toate rularile\n'); const inainte = amprente(); const lucru = fs.mkdtempSync(path.join(os.tmpdir(), 'aeresecrets-control-'));