nx_esign_lib.nx
buildroot/runtime/nx_esign_lib.nx
about
nx_esign_lib.nx -- E-SIGNATURE LEGAL VALIDITY: the ESIGN/UETA four-element test + the eIDAS tier
ladder (SES/AES/QES). The gap this closes: a tamper-evident hash chain (nx_sign_envelope) proves a
document was NOT ALTERED. It does not answer the only two questions a court asks -- was this signature
legally executed, and what legal effect does it carry. DocuSign/Adobe-class products answer both;
a bare hash chain answers neither.
US (ESIGN 15 USC 7001 + UETA s2(8)/s7): enforceable ONLY on all FOUR of --
1 INTENT the signer performed an affirmative act intending to sign
2 CONSENT the parties agreed to transact electronically
3 ASSOCIATION the signature is logically/cryptographically bound to THAT record
4 RETENTION the record is tamper-evident, accurately reproducible, and accessible
CONSUMER OVERLAY (ESIGN 101(c)) -- a consumer signer additionally requires paper-copy right,
withdrawal right, hardware/software disclosure, and a DEMONSTRATED ability to access the record.
A consumer transaction missing these is unenforceable even with all four base elements present.
EU (eIDAS Art 3/25/26): SES < AES < QES. THE DISTINCTION MOST IMPLEMENTATIONS BLUR: Art 25(1) says no
electronic signature may be denied legal effect merely for being electronic -- that is ADMISSIBILITY,
and it reaches every tier. Art 25(2) grants EQUIVALENCE TO A HANDWRITTEN SIGNATURE to QES *alone*.
Conflating them is the error that loses cases, so they are SEPARATE predicates that never collapse.
STRUCTURE (two layers, deliberately): a PURE DECISION CORE holding the statutory rules as total
functions over resolved flags, and REGISTRY ADAPTERS that fetch facts and delegate to it. Every rule
exists exactly once, so the stored-fact path can never disagree with the rule. See the core's own
note for why this split is load-bearing rather than cosmetic.
FAIL-CLOSED BY CONSTRUCTION: only the exact string "yes" asserts a stored element, and only the
integer 1 asserts a resolved one. Absent, empty, "true", "1", "YES" all leave it UNSATISFIED. An
element nobody recorded is an element nobody performed; a signature is never valid by omission.
SCALE ENVELOPE (declared, measured): the pure core is O(1) and allocation-free. Each adapter costs one
reg_get per element (~70us). reg_put costs ~678ms and is the binding cost of WRITING facts, never of
evaluating them -- see debt 1785519597. license_tier: ORIGINAL LIB.
dependencies 1 imports · 6 importers
imports: nx_matter_lib.nx
imported by: nx_esign_eidas_gate.nxnx_esign_gate.nxnx_esign_probe.nxnx_esign_probe_test.nxnx_esign_pure_gate.nxnx_legal_svc.nx
structs
| none |
consts
| 36 | const ES_NONE: i64 = 0 |
| 37 | const ES_SES: i64 = 1 |
| 38 | const ES_AES: i64 = 2 |
| 39 | const ES_QES: i64 = 3 |
| 41 | const ES_RECBUF: i64 = 512 |
| 42 | const ES_IDBUF: i64 = 256 |
functions
| 59 | func es_is1(v: i64) -> i64 |
| 64 | func es_elements_pure(intent: i64, consent: i64, assoc: i64, retention: i64) -> i64 |
| 74 | func es_ueta_pure(intent: i64, consent: i64, assoc: i64, retention: i64) -> i64 |
| 80 | func es_consumer_pure(is_consumer: i64, paper: i64, withdrawal: i64, hwsw: i64, access: i64) -> i64 |
| 90 | func es_aes_pure(unique: i64, sigid: i64, sole: i64, tamper: i64) -> i64 |
| 100 | func es_tier_pure(sig_data: i64, unique: i64, sigid: i64, sole: i64, tamper: i64, qscd: i64, qcert: i64) -> i64 |
| 112 | func es_admissible_pure(tier: i64) -> i64 |
| 118 | func es_handwritten_pure(tier: i64) -> i64 |
| 129 | func es_key(sig: *u8, field: *u8, out: *u8) -> i64 |
| 138 | func es_set(prefix: *u8, sig: *u8, field: *u8, val: *u8) -> i64 |
| 150 | func es_get(prefix: *u8, sig: *u8, field: *u8, out: *u8) -> i64 |
| 164 | func es_yes(prefix: *u8, sig: *u8, field: *u8) -> i64 called by 10: es_intentes_consentes_associationes_retentiones_consumer_okes_aes_ok+4 calls 2: es_getmt_streq |
| 176 | func es_intent(prefix: *u8, sig: *u8) -> i64 { return es_yes(prefix, sig, "intent" as *u8) } |
| 177 | func es_consent(prefix: *u8, sig: *u8) -> i64 { return es_yes(prefix, sig, "consent" as *u8) } |
| 178 | func es_association(prefix: *u8, sig: *u8) -> i64 { return es_yes(prefix, sig, "association" as *u8) } |
| 179 | func es_retention(prefix: *u8, sig: *u8) -> i64 { return es_yes(prefix, sig, "retention" as *u8) } |
| 181 | func es_elements(prefix: *u8, sig: *u8) -> i64 |
| 185 | func es_ueta_valid(prefix: *u8, sig: *u8) -> i64 |
| 189 | func es_is_consumer(prefix: *u8, sig: *u8) -> i64 |
| 196 | func es_consumer_ok(prefix: *u8, sig: *u8) -> i64 |
| 200 | func es_esign_valid(prefix: *u8, sig: *u8) -> i64 |
| 205 | func es_aes_ok(prefix: *u8, sig: *u8) -> i64 |
| 209 | func es_eidas_tier(prefix: *u8, sig: *u8) -> i64 called by 5: maines_qes_okes_admissiblees_handwritten_equivalentes_ready calls 2: es_tier_purees_yes |
| 213 | func es_qes_ok(prefix: *u8, sig: *u8) -> i64 calls 1: es_eidas_tier |
| 218 | func es_tier_label(tier: i64, out: *u8) -> i64 |
| 227 | func es_admissible(prefix: *u8, sig: *u8) -> i64 |
| 231 | func es_handwritten_equivalent(prefix: *u8, sig: *u8) -> i64 |
| 237 | func es_audit_missing_pure(identity: i64, auth: i64, ts: i64, hash: i64, consent_rec: i64, seq: i64) -> i64 |
| 248 | func es_audit_missing(prefix: *u8, sig: *u8) -> i64 |
| 252 | func es_audit_complete(prefix: *u8, sig: *u8) -> i64 |
| 259 | func es_ready_pure(esign_ok: i64, tier: i64, audit_miss: i64) -> i64 |
| 266 | func es_ready(prefix: *u8, sig: *u8) -> i64 |