nx_evattest.nx
buildroot/runtime/nx_evattest.nx
about
nx_evattest.nx -- SIGNED EVIDENCE ATTESTATIONS, shared. Closes seq1367: the human leg of the evidence law
was a plain-text row, so anything that could write knowledge/status/ could mint a human sign-off and drive
a domain to PROVEN. The `require_human` clause exists precisely so an automated actor cannot certify its
own work; an unsigned carrier let exactly that happen through the back door.
(Named nx_evattest, not nx_attest: runtime/nx_attest.nx already exists and is a different organ -- an
append-only Merkle log for privileged operations. Check before you name.)
★★WHAT SIGNING HONESTLY BUYS, AND WHAT IT DOES NOT.
It does NOT create an absolute barrier against an agent that can read the filesystem -- a private key on
disk is readable by anything with disk access, and pretending otherwise would be exactly the comfortable
fiction this workstream exists to delete. What it DOES buy, all of it real:
* ATTRIBUTION -- every attestation names the key that made it, verifiably.
* TAMPER-EVIDENCE -- a row cannot be edited afterwards without invalidating its signature.
* ROLE SEPARATION -- the structural one: a human-class row signed by a key REGISTERED AS A MACHINE KEY
is REFUSED. The automation signing a human attestation is not merely discouraged, it is mechanically
rejected, and forging one requires a key the automation is not supposed to hold.
* AUDITABILITY -- if a human row ever were signed by the wrong key, that is provable afterwards.
This library contains NO key generation and NO signing path. It verifies, and it refuses. Minting a human
attestation is an act the operator performs with a key the operator holds -- that is the whole clause.
ROW FORMAT (one attestation per line, knowledge/status/evclass_<domain>.conf):
class=human verdict=pass scope=<what was examined> signer=<who> epoch=<ts> pub=<64hex> sig=<128hex>
The signature covers the CLAIM PREFIX: every byte of the row up to (and excluding) " pub=". So class,
verdict, scope, signer and epoch are all immutable under the signature -- a signed attestation cannot be
re-pointed at a different class, claim, or time. The key and signature themselves sit outside the signed
region, so a signer need not predict the encoding of its own key.
KEY REGISTRY (knowledge/attest_keys.conf): role=human|llm|machine pub=<64hex> name=<who>
An unregistered key verifies cryptographically but is still REFUSED: a valid signature from a stranger is
not an authorisation. license_tier: ORIGINAL
dependencies 2 imports · 4 importers
imports: nx_syscalls.nxnx_ed25519_signature.nx
imported by: nx_attest_ceremony.nxnx_evattest_cli.nxnx_evattest_gate.nxnx_sota_status.nx
structs
| none |
consts
| 35 | const AT_MAGIC_4000: i64 = 4000 |
| 36 | const AT_MAGIC_4096: i64 = 4096 |
| 38 | const AT_CLASS_NONE: i64 = 0 |
| 39 | const AT_CLASS_MECH: i64 = 1 |
| 40 | const AT_CLASS_LLM: i64 = 2 |
| 41 | const AT_CLASS_HUMAN: i64 = 4 |
| 47 | const AT_CLASS_ORACLE: i64 = 8 |
| 51 | const AT_CLASS_EXPERIENTIAL: i64 = 16 |
| 53 | const AT_OK: i64 = 0 |
| 54 | const AT_ERR_NOSIG: i64 = 1 |
| 55 | const AT_ERR_BADSIG: i64 = 2 |
| 56 | const AT_ERR_UNKNOWNKEY: i64 = 3 |
| 57 | const AT_ERR_ROLE: i64 = 4 |
| 60 | const AT_ERR_NOTDERIVED: i64 = 5 |
functions
| 62 | func at_hexval(c: i64) -> i64 called by 1: at_unhex |
| 68 | func at_unhex(buf: *u8, off: i64, n: i64, out: *u8) -> i64 |
| 80 | func at_find(buf: *u8, s: i64, e: i64, key: *u8, kl: i64) -> i64 |
| 94 | func at_key_role(conf: *u8, cn: i64, pub: *u8) -> i64 |
| 128 | func at_verify_row(buf: *u8, s: i64, e: i64, claimed: i64, conf: *u8, cn: i64) -> i64 |
| 191 | func at_err_name(rc: i64) -> *u8 called by 1: main |