code wiki / _hdl_build / nx_hostop_apply_gate.nx
nx_hostop_apply_gate.nx source
↩ module page · 54 lines · 4633 B
1// nx_hostop_apply_gate.nx -- R2/R3/R5 PROOF: atomic host-swap + host-rollback, NEVER-BRICK by construction.
2// In a SANDBOX host-root (NOT the real .240): apply v1 then v2 (atomic, prev kept), roll back to v1, and a verified
3// apply that fail-closes a sha-mismatch (host untouched). Never-brick: atomic rename (no .tmp residue) + reversible
4// (.prev). File-based. license_tier: ORIGINAL expect_exit: 0
5import "nx_syscalls.nx"
6import "nx_hostop.nx"
7import "nx_runpath.nx"
8
9func g_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func g_n(v: i64) -> i64 { var m: i64=v; if m<0{g_w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
11func g_row(id: *u8, ok: i64, pass: *i64) -> i64 { g_w(" " as *u8); g_w(id); g_w(": " as *u8); if ok==1 { g_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { g_w("FAIL\n" as *u8) } return 0 }
12func sv_write(path: *u8, content: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd<0 { return 0 } var n: i64=0; while content[n]!=(0 as u8){n=n+1} sys_write(fd, content, n); sys_close(fd); return 1 }
13func g_mkdir(D: *u8, name: *u8) -> *u8 { let p: *u8 = sys_mmap(700); pub_join(D, name, p); __syscall(83, p as i64, 493, 0, 0, 0, 0); return p }
14func has_str(path: *u8, needle: *u8) -> i64 { let lp: *i64 = sys_mmap(8) as *i64; let d: *u8 = sys_read_file(path, lp); if (d as i64)==0 { return 0 } return pub_substr(d, lp[0], needle) }
15
16func main() -> i64 {
17 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0
18 g_w("=== NX-HOSTOP-APPLY GATE (atomic host-swap + rollback, never-brick; SANDBOX host-root) ===\n" as *u8)
19 let wsid: *u8 = sys_mmap(64); rp_wsid(wsid); rp_ensure(wsid)
20 let D: *u8 = sys_mmap(512); rp_path(wsid, "hoa" as *u8, D); __syscall(83, D as i64, 493, 0, 0, 0, 0)
21 let host: *u8 = g_mkdir(D, "host" as *u8) // SANDBOX host-root (stands in for the live host)
22 let src1: *u8 = sys_mmap(700); pub_join(D, "v1.src" as *u8, src1); sv_write(src1, "HOST-V1\n" as *u8)
23 let src2: *u8 = sys_mmap(700); pub_join(D, "v2.src" as *u8, src2); sv_write(src2, "HOST-V2\n" as *u8)
24
25 let hp: *u8 = sys_mmap(700); pub_join(host, "page.html" as *u8, hp)
26 let tmp: *u8 = sys_mmap(700); pub_pcat(hp, ".tmp" as *u8, tmp)
27 __syscall(87, hp as i64,0,0,0,0,0); __syscall(87, tmp as i64,0,0,0,0,0) // clean baseline
28
29 hostop_apply(src1, host, "page.html" as *u8) // apply v1
30 let a_v1: i64 = has_str(hp, "HOST-V1" as *u8)
31 hostop_apply(src2, host, "page.html" as *u8) // apply v2 (keeps v1 as .prev)
32 let a_v2: i64 = has_str(hp, "HOST-V2" as *u8)
33 let no_residue: i64 = (pub_exists(tmp)==0) as i64 // never-brick: no half-written .tmp left
34 let rb: i64 = hostop_host_rollback(host, "page.html" as *u8) // roll back to v1
35 let back_v1: i64 = has_str(hp, "HOST-V1" as *u8)
36
37 // verified-apply fail-closed: a sha-mismatch must NOT touch the host (need a publisher ledger + staged file)
38 let live: *u8 = g_mkdir(D, "publive" as *u8)
39 let led: *u8 = sys_mmap(700); pub_join(D, "pub_ledger.tsv" as *u8, led); __syscall(87, led as i64,0,0,0,0,0)
40 let pdst: *u8 = sys_mmap(700); pub_join(live, "p.html" as *u8, pdst); sv_write(pdst, "STAGED-GOOD\n" as *u8)
41 pub_record_ledger(led, "shaP" as *u8, "p.html" as *u8, "site" as *u8)
42 let hp2: *u8 = sys_mmap(700); pub_join(host, "p.html" as *u8, hp2); __syscall(87, hp2 as i64,0,0,0,0,0)
43 let bad: i64 = hostop_apply_verified(led, live, host, "p.html" as *u8, "WRONGSHA" as *u8) // sha-mismatch
44 let host_untouched: i64 = (pub_exists(hp2)==0) as i64
45
46 g_w(" apply v1=" as *u8); g_n(a_v1); g_w(" v2=" as *u8); g_n(a_v2); g_w(" no_tmp_residue=" as *u8); g_n(no_residue); g_w(" rollback=" as *u8); g_n(rb); g_w(" back_to_v1=" as *u8); g_n(back_v1); g_w(" verified_bad=" as *u8); g_n(bad); g_w(" host_untouched=" as *u8); g_n(host_untouched); g_w("\n" as *u8)
47 g_row("ATOMIC host-swap: apply v1 then v2 (host serves v2), NO .tmp residue (never half-applied)" as *u8, a_v1 & a_v2 & no_residue, pass)
48 g_row("HOST-ROLLBACK: restores the previous host state (back to v1)" as *u8, ((rb==1) as i64) & back_v1, pass)
49 g_row("NEVER-BRICK fail-closed: a sha-mismatch verified-apply leaves the host UNTOUCHED" as *u8, ((bad==0) as i64) & host_untouched, pass)
50
51 g_w("NX-HOSTOP-APPLY rows=3 pass=" as *u8); g_n(pass[0])
52 if pass[0]==3 { g_w(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
53 g_w(" verdict=RED\n" as *u8); sys_exit(1); return 1
54}