code wiki / (root) / nx_measurement_binding_artifact_gate.nx

nx_measurement_binding_artifact_gate.nx source

↩ module page · 186 lines · 10332 B

1// Capture the actual staged owner without changing its command/API contract. 2// Only caller-named exclusive /tmp files are written. Existing board artifacts are compared. 3// license_tier: ORIGINAL; expect_exit: 0 4import "nx_gatekit_lib.nx" 5import "nx_gate_verdict.nx" 6import "nx_estate_path.nx" 7import "nx_json_lib.nx" 8 9const BC_FILE_MODE: i64 = 0x180 // POSIX owner-read/write temporary artifact mode 10const BC_EXEC_FAILED: i64 = 127 11const BC_CAPTURE_FAILED: i64 = 125 12const BC_EINTR: i64 = 4 13const BC_BOARD_JSON: *u8 = "knowledge/status/sota_board.json" 14const BC_BOARD_LEDGER: *u8 = "knowledge/status/sota_board.ledger" 15 16func bc_prefix_ok(prefix: *u8) -> i64 { 17 let n: i64 = gk_len(prefix) 18 if n <= gk_len("/tmp/" as *u8) { return 0 } 19 if n+gk_len(".invalid-domain-artifact.json" as *u8)+gk_len("/tmp/../" as *u8)+1 > SYS_PATH_MAX { return 0 } 20 let root: *u8 = "/tmp/" as *u8 21 var i: i64 = 0 22 while i < gk_len(root) { if prefix[i] != root[i] { return 0 } i = i+1 } 23 while i < n { 24 let c: i64 = prefix[i] as i64 25 var ok: i64 = 0 26 if c >= 97 { if c <= 122 { ok = 1 } } 27 if c >= 65 { if c <= 90 { ok = 1 } } 28 if c >= 48 { if c <= 57 { ok = 1 } } 29 if c == 95 { ok = 1 } 30 if c == 45 { ok = 1 } 31 if ok == 0 { return 0 } 32 i = i+1 33 } 34 return 1 35} 36func bc_equal(before: *u8, bn: i64, after: *u8, an: i64) -> i64 { 37 if bn <= 0 { return 0 } 38 if bn != an { return 0 } 39 if (before as i64) <= 0 { return 0 } 40 if (after as i64) <= 0 { return 0 } 41 var i: i64 = 0 42 while i < bn { if before[i] != after[i] { return 0 } i = i+1 } 43 return 1 44} 45func bc_capture(elf: *u8, domain: *u8, out: *u8) -> i64 { 46 let argv: *i64 = sys_mmap(4*8) as *i64 47 let envp: *i64 = sys_mmap(8) as *i64 48 let status: *i64 = sys_mmap(8) as *i64 49 if (argv as i64) <= 0 { return BC_CAPTURE_FAILED } 50 if (envp as i64) <= 0 { return BC_CAPTURE_FAILED } 51 if (status as i64) <= 0 { return BC_CAPTURE_FAILED } 52 let mode: *u8 = "bindings" as *u8 53 argv[0] = elf as i64; argv[1] = mode as i64; argv[2] = domain as i64; argv[3] = 0 54 envp[0] = 0; status[0] = 0 55 let fd: i64 = sys_openat_exclusive(out, BC_FILE_MODE) 56 if fd < 0 { return BC_CAPTURE_FAILED } 57 let pid: i64 = sys_fork() 58 if pid < 0 { sys_close(fd); return BC_CAPTURE_FAILED } 59 if pid == 0 { 60 if fd != 1 { if sys_dup3(fd, 1, 0) < 0 { sys_exit(BC_CAPTURE_FAILED) } } 61 sys_execve_clean(elf, argv, envp) 62 sys_exit(BC_EXEC_FAILED) 63 } 64 var waited: i64 = sys_wait4(pid, status, 0) 65 while waited == 0-BC_EINTR { waited = sys_wait4(pid, status, 0) } 66 let synced: i64 = sys_fsync(fd) 67 sys_close(fd) 68 if waited != pid { return BC_CAPTURE_FAILED } 69 if synced < 0 { return BC_CAPTURE_FAILED } 70 return gk_wait_code(status[0]) 71} 72func bc_case(elf: *u8, prefix: *u8, suffix: *u8, domain: *u8, expected_rc: i64, marker: *u8, ctr: *i64) -> i64 { 73 let path: *u8 = sys_mmap(SYS_PATH_MAX) 74 let size: *i64 = sys_mmap(8) as *i64 75 var allocated: i64 = 0 76 if (path as i64) > 0 { if (size as i64) > 0 { allocated = 1 } } 77 gv_check("capture-case-buffers-allocated" as *u8, allocated, ctr) 78 if allocated == 0 { return 0 } 79 let used: i64 = gk_cat(path, 0, prefix) 80 gk_cat(path, used, suffix) 81 let rc: i64 = bc_capture(elf, domain, path) 82 gv_puts("capture_path=" as *u8); gv_puts(path); gv_puts(" exit=" as *u8); gv_num(rc) 83 let output: *u8 = sys_read_file(path, size) 84 gv_puts(" complete_file_bytes=" as *u8); gv_num(size[0]); gv_puts("\n" as *u8) 85 gv_check("staged-owner-exit-matches-contract" as *u8, rc == expected_rc, ctr) 86 var complete: i64 = 0 87 if (output as i64) > 0 { if size[0] > 1 { 88 if output[0] == (123 as u8) { if output[size[0]-1] == (10 as u8) { 89 if output[size[0]-2] == (125 as u8) { complete = gk_has(output, marker) } 90 } } 91 } } 92 gv_check("complete-file-json-envelope-and-case-marker" as *u8, complete, ctr) 93 sys_free_file(output, size[0]) 94 return complete 95} 96func bc_artifact(elf: *u8, prefix: *u8, ctr: *i64) -> i64 { 97 let path: *u8 = sys_mmap(SYS_PATH_MAX) 98 let invalid: *u8 = sys_mmap(SYS_PATH_MAX) 99 let traversal: *u8 = sys_mmap(SYS_PATH_MAX) 100 let log: *u8 = sys_mmap(GK_BUF) 101 let ln: *i64 = sys_mmap(8) as *i64 102 let bn: *i64 = sys_mmap(8) as *i64 103 let an: *i64 = sys_mmap(8) as *i64 104 let reported: *i64 = sys_mmap(8) as *i64 105 var ready: i64 = 0 106 if (path as i64) > 0 { if (invalid as i64) > 0 { if (traversal as i64) > 0 { if (log as i64) > 0 { 107 if (ln as i64) > 0 { if (bn as i64) > 0 { if (an as i64) > 0 { if (reported as i64) > 0 { ready = 1 } } } } 108 } } } } 109 gv_check("artifact-case-buffers-allocated" as *u8, ready, ctr) 110 if ready == 0 { return 0 } 111 let used: i64 = gk_cat(path, 0, prefix) 112 gk_cat(path, used, ".gameengine-artifact.json" as *u8) 113 let badused: i64 = gk_cat(invalid, 0, prefix) 114 gk_cat(invalid, badused, ".invalid-domain-artifact.json" as *u8) 115 let rc: i64 = gk_run_capture(elf, "bindings" as *u8, "gameengine" as *u8, path, 0 as *u8, log, GK_BUF, ln) 116 gv_check("artifact-command-exits-zero" as *u8, rc == 0, ctr) 117 var receipt: i64 = 0 118 if gk_has(log, "\"resource\":\"domain-bindings-artifact\"" as *u8) == 1 { 119 if gk_has(log, "\"ready\":true" as *u8) == 1 { if gk_has(log, "\"retained_partial\":false" as *u8) == 1 { receipt = 1 } } 120 } 121 gv_check("artifact-has-completion-receipt" as *u8, receipt, ctr) 122 gv_puts("artifact_receipt=" as *u8); sys_write(1, log, ln[0]) 123 let before: *u8 = sys_read_file(path, bn) 124 let got: i64 = jx_get_int(log, ln[0], 0, "bytes_written" as *u8, reported) 125 var same_size: i64 = 0 126 if got > 0 { if bn[0] > 0 { if reported[0] == bn[0] { same_size = 1 } } } 127 gv_check("artifact-receipt-counts-complete-file-bytes" as *u8, same_size, ctr) 128 var full: i64 = 0 129 if (before as i64) > 0 { if bn[0] > 1 { if before[bn[0]-2] == (125 as u8) { 130 if before[bn[0]-1] == (10 as u8) { full = gk_has(before, "\"domain\":\"gameengine\"" as *u8) } 131 } } } 132 gv_check("artifact-retains-complete-report-envelope" as *u8, full, ctr) 133 let again: i64 = gk_run_capture(elf, "bindings" as *u8, "gameengine" as *u8, path, 0 as *u8, log, GK_BUF, ln) 134 gv_check("existing-artifact-path-refused" as *u8, again == 3, ctr) 135 gv_check("existing-artifact-refusal-is-explicit" as *u8, gk_has(log, "\"reason\":\"output_open_refused\"" as *u8), ctr) 136 let after: *u8 = sys_read_file(path, an) 137 gv_check("existing-artifact-byte-identical-after-refused-reuse" as *u8, bc_equal(before, bn[0], after, an[0]), ctr) 138 sys_free_file(after, an[0]); sys_free_file(before, bn[0]) 139 let bad_domain: i64 = gk_run_capture(elf, "bindings" as *u8, "../" as *u8, invalid, 0 as *u8, log, GK_BUF, ln) 140 gv_check("bad-domain-refused-before-artifact-creation" as *u8, bad_domain == 3, ctr) 141 gv_check("bad-domain-created-no-artifact" as *u8, gk_exists(invalid) == 0, ctr) 142 // Even a broken validator resolves this spelling to the existing caller-owned /tmp artifact. 143 let tused: i64 = gk_cat(traversal, 0, "/tmp/../" as *u8) 144 gk_cat(traversal, tused, path) 145 let bad_path: i64 = gk_run_capture(elf, "bindings" as *u8, "gameengine" as *u8, traversal, 0 as *u8, log, GK_BUF, ln) 146 gv_check("output-traversal-refused" as *u8, bad_path == 3, ctr) 147 gv_check("output-traversal-refusal-is-explicit" as *u8, gk_has(log, "bad_output_path" as *u8), ctr) 148 let too_many: i64 = gk_run_capture(elf, "bindings" as *u8, "gameengine" as *u8, invalid, "unexpected" as *u8, log, GK_BUF, ln) 149 gv_check("five-argument-command-remains-refused" as *u8, too_many == 3, ctr) 150 gv_check("bad-arity-created-no-artifact" as *u8, gk_exists(invalid) == 0, ctr) 151 return full 152} 153func main(argc: i64, argv: *i64) -> i64 { 154 if argc != 3 { gv_puts("usage: capture-gate <staged-owner-path> </tmp/unique-basename>\n" as *u8); return 3 } 155 let elf: *u8 = argv[1] as *u8 156 let prefix: *u8 = argv[2] as *u8 157 if bc_prefix_ok(prefix) == 0 { gv_puts("REFUSE temporary basename must remain directly under /tmp\n" as *u8); return 3 } 158 if ep_anchor() < 0 { gv_puts("REFUSE estate anchor unavailable\n" as *u8); return 3 } 159 let ctr: *i64 = gv_ctr() 160 gv_head("Actual staged binding command: complete capture and unchanged board artifacts" as *u8) 161 let jn: *i64 = sys_mmap(8) as *i64 162 let ln: *i64 = sys_mmap(8) as *i64 163 let an: *i64 = sys_mmap(8) as *i64 164 var allocated: i64 = 0 165 if (jn as i64) > 0 { if (ln as i64) > 0 { if (an as i64) > 0 { allocated = 1 } } } 166 gv_check("board-comparison-buffers-allocated" as *u8, allocated, ctr) 167 if allocated == 0 { return gv_verdict("NX-BINDINGS-CAPTURE" as *u8, ctr, "allocation failed before baseline reads" as *u8) } 168 let jb: *u8 = sys_read_file(BC_BOARD_JSON, jn) 169 let lb: *u8 = sys_read_file(BC_BOARD_LEDGER, ln) 170 var ready: i64 = 0 171 if (jb as i64) > 0 { if jn[0] > 0 { if (lb as i64) > 0 { if ln[0] > 0 { ready = 1 } } } } 172 gv_check("existing-board-artifacts-readable-before-command" as *u8, ready, ctr) 173 if ready == 0 { return gv_verdict("NX-BINDINGS-CAPTURE" as *u8, ctr, "no board side-effect claim without baseline bytes" as *u8) } 174 bc_case(elf, prefix, ".charsim.json" as *u8, "charsim" as *u8, 0, "\"domain\":\"charsim\"" as *u8, ctr) 175 bc_case(elf, prefix, ".gameengine.json" as *u8, "gameengine" as *u8, 0, "\"domain\":\"gameengine\"" as *u8, ctr) 176 bc_case(elf, prefix, ".bad-domain.json" as *u8, "../" as *u8, 3, "\"reason\":\"bad_domain\"" as *u8, ctr) 177 bc_case(elf, prefix, ".missing-argument.json" as *u8, 0 as *u8, 3, "usage: nx_sota_status bindings" as *u8, ctr) 178 bc_artifact(elf, prefix, ctr) 179 let ja: *u8 = sys_read_file(BC_BOARD_JSON, an) 180 gv_check("existing-board-json-byte-identical-after-all-cases" as *u8, bc_equal(jb, jn[0], ja, an[0]), ctr) 181 sys_free_file(ja, an[0]) 182 let la: *u8 = sys_read_file(BC_BOARD_LEDGER, an) 183 gv_check("existing-board-ledger-byte-identical-after-all-cases" as *u8, bc_equal(lb, ln[0], la, an[0]), ctr) 184 sys_free_file(la, an[0]); sys_free_file(jb, jn[0]); sys_free_file(lb, ln[0]) 185 return gv_verdict("NX-BINDINGS-CAPTURE" as *u8, ctr, "complete artifacts retained at printed paths; JSON structure and semantic checker must also pass before promotion" as *u8) 186}