pq-secrets: the negative control finds its sibling components in the published layout (pq-kms/, identity/, proof-kinds/, verify-layer/ beside it) as well as in the development tree, and refuses with the list of what is missing when neither is complete; README: compliance and Travel Rule name the verifier they need; conformance README: the online run of 2026-10-18 21:25Z

This commit is contained in:
Aere Network 2026-10-19 01:09:03 +03:00
parent ad16b1f69b
commit b544cc1b11
4 changed files with 31 additions and 8 deletions

View File

@ -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 <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) |

View File

@ -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

View File

@ -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

View File

@ -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-'));