code wiki / _hdl_build / nx_studio_e2e_gate.nx
nx_studio_e2e_gate.nx source
↩ module page · 135 lines · 8620 B
1// nx_studio_e2e_gate.nx -- SOVEREIGN end-to-end gate for the capability-adaptive studio (no shells, no curl).
2// Forks the real studio daemon (/tmp/nx_sitegen_studio_daemon.sov.elf -- build it --build-only first) and drives
3// it over raw sovereign sockets (nx_http_client's sockaddr builder), exercising the WHOLE flow over real HTTP:
4// the PICKER front door, each tier surface (guided/blocks/freeform), and POST /build through se_build_tier for
5// each tier -- governed page out, incomplete refused, hostile field escaped. Proves the multi-tier WYSIWYG works
6// end-to-end the sovereign way. Appends a CMSGATE row to knowledge/status/cms_gate.log on all-pass.
7// PRE: ./_offc/nx_sov_build_run.elf nx_sitegen_studio_daemon --build-only (produces the .sov.elf forked here)
8// license_tier: ORIGINAL
9import "nx_http_client.nx"
10import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
11import "nx_syscalls.nx"
12
13const E_PORT: i64 = 8101
14const E_DAEMON: *u8 = "/tmp/nx_sitegen_studio_daemon.sov.elf" as *u8
15
16func ew(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
17func ecat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var k: i64=0; while s[k]!=(0 as u8){dst[o]=s[k];o=o+1;k=k+1} return o }
18func ecatn(dst: *u8, off: i64, s: *u8, n: i64) -> i64 { var o: i64=off; var k: i64=0; while k<n{dst[o]=s[k];o=o+1;k=k+1} return o }
19func enm(dst: *u8, off: i64, v: i64) -> i64 { var o: i64=off; let t: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; 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; while i<k{dst[o]=t[k-1-i];o=o+1;i=i+1} return o }
20func elen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
21func efind(buf: *u8, n: i64, pat: *u8, plen: i64) -> i64 {
22 if plen==0 { return 0-1 }
23 var i: i64=0
24 while i+plen<=n { var j: i64=0; var ok: i64=1; while j<plen { if (buf[i+j] as i64)!=(pat[j] as i64){ok=0;j=plen} else {j=j+1} } if ok==1 { return i } i=i+1 }
25 return 0-1
26}
27func ehas(buf: *u8, n: i64, s: *u8) -> i64 { var pl: i64=0; while s[pl]!=(0 as u8){pl=pl+1} if efind(buf,n,s,pl)>=0 { return 1 } return 0 }
28func erow(id: i64, ok: i64, what: *u8) -> i64 { ew("E2EROW " as *u8); let b: *u8=sys_mmap(8); b[0]=(48+id) as u8; sys_write(1,b,1); ew(" " as *u8); if ok==1 { ew("PASS " as *u8) } else { ew("FAIL " as *u8) } ew(what); ew("\n" as *u8); return ok }
29
30func e_send(reqbuf: *u8, reqlen: i64, resp: *u8, cap: i64) -> i64 {
31 let addr: *u8 = sys_mmap(16)
32 nx_http_client_sockaddr_ipv4(addr, 127, 0, 0, 1, E_PORT)
33 let fd: i64 = sys_socket(2, 1, 0)
34 if fd < 0 { return 0 - 1 }
35 if nx_connect_bounded(fd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0 - 1 }
36 sys_write(fd, reqbuf, reqlen)
37 var off: i64 = 0
38 var keep: i64 = 1
39 while keep == 1 {
40 if off >= cap { keep = 0 } else { let r: i64 = sys_read(fd, (resp + off) as *u8, cap - off); if r <= 0 { keep = 0 } else { off = off + r } }
41 }
42 sys_close(fd)
43 return off
44}
45func e_get(req: *u8, path: *u8) -> i64 {
46 var o: i64 = ecat(req, 0, "GET " as *u8); o = ecat(req, o, path)
47 o = ecat(req, o, " HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n" as *u8)
48 return o
49}
50func e_post(req: *u8, path: *u8, body: *u8) -> i64 {
51 let blen: i64 = elen(body)
52 var o: i64 = ecat(req, 0, "POST " as *u8); o = ecat(req, o, path)
53 o = ecat(req, o, " HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: text/plain\r\nContent-Length: " as *u8)
54 o = enm(req, o, blen); o = ecat(req, o, "\r\nConnection: close\r\n\r\n" as *u8)
55 o = ecatn(req, o, body, blen)
56 return o
57}
58
59func main() -> i64 {
60 // fork + exec the real studio daemon (listens on :8101, serves web_assets/_studio/* from cwd=nxc2)
61 let pid: i64 = sys_fork()
62 if pid == 0 {
63 let argv: *i64 = sys_mmap(64) as *i64
64 argv[0] = E_DAEMON as i64; argv[1] = 0
65 let envp: *i64 = sys_mmap(16) as *i64; envp[0] = 0
66 sys_execve(E_DAEMON, argv, envp)
67 sys_exit(127)
68 }
69 let resp: *u8 = sys_mmap(262144)
70 let req: *u8 = sys_mmap(16384)
71
72 // wait for bind (bounded retry on GET /)
73 var tries: i64 = 0
74 while tries < 400 {
75 let g: i64 = e_send(req, e_get(req, "/" as *u8), resp, 262143)
76 if g > 0 { tries = 400 } else { tries = tries + 1 }
77 }
78
79 var rows: i64 = 0
80 var pass: i64 = 0
81 var ok: i64 = 0
82
83 // R0: GET / -> the PICKER front door
84 let n0: i64 = e_send(req, e_get(req, "/" as *u8), resp, 262143)
85 ok = 0; if ehas(resp,n0,"How do you want to build" as *u8)==1 { if ehas(resp,n0,"/freeform" as *u8)==1 { ok=1 } }
86 rows=rows+1; pass=pass+erow(0, ok, "GET / -> the capability PICKER front door" as *u8)
87
88 // R1: GET /guided -> the guided wizard
89 let n1: i64 = e_send(req, e_get(req, "/guided" as *u8), resp, 262143)
90 ok = 0; if ehas(resp,n1,"id=\"brand\"" as *u8)==1 { if ehas(resp,n1,"tier|guided" as *u8)==1 { ok=1 } }
91 rows=rows+1; pass=pass+erow(1, ok, "GET /guided -> the guided wizard surface" as *u8)
92
93 // R2: GET /blocks -> the block editor
94 let n2: i64 = e_send(req, e_get(req, "/blocks" as *u8), resp, 262143)
95 ok = 0; if ehas(resp,n2,"data-add" as *u8)==1 { if ehas(resp,n2,"Nishi Studio" as *u8)==1 { ok=1 } }
96 rows=rows+1; pass=pass+erow(2, ok, "GET /blocks -> the block editor surface" as *u8)
97
98 // R3: GET /freeform -> the free-form canvas
99 let n3: i64 = e_send(req, e_get(req, "/freeform" as *u8), resp, 262143)
100 ok = 0; if ehas(resp,n3,"data-add=\"heading\"" as *u8)==1 { if ehas(resp,n3,"pointerdown" as *u8)==1 { ok=1 } }
101 rows=rows+1; pass=pass+erow(3, ok, "GET /freeform -> the free-form canvas surface" as *u8)
102
103 // R4: POST /build tier|guided -> governed guided page (over HTTP)
104 let n4: i64 = e_send(req, e_post(req, "/build" as *u8, "tier|guided\nbrand|E2E Brand\ncta|Go\ncta_href|#g\nheadline|E2E Headline\nsub|s\nsearch|/s\ncard_title|A\ncard_body|b\nstep1|1\nstep2|2\ntrust|T\nfooter|F\n" as *u8), resp, 262143)
105 ok = 0; if ehas(resp,n4,"E2E Brand" as *u8)==1 { if ehas(resp,n4,"E2E Headline" as *u8)==1 { if ehas(resp,n4,"width=device-width" as *u8)==1 { ok=1 } } }
106 rows=rows+1; pass=pass+erow(4, ok, "POST /build tier|guided -> governed guided page (HTTP)" as *u8)
107
108 // R5: POST /build tier|freeform -> governed canvas, placement honored (over HTTP)
109 let n5: i64 = e_send(req, e_post(req, "/build" as *u8, "tier|freeform\ntitle|E2E\nel|heading|30|40|400|E2E Canvas Heading|\n" as *u8), resp, 262143)
110 ok = 0; if ehas(resp,n5,"E2E Canvas Heading" as *u8)==1 { if ehas(resp,n5,"left:30px;top:40px;width:400px" as *u8)==1 { ok=1 } }
111 rows=rows+1; pass=pass+erow(5, ok, "POST /build tier|freeform -> governed canvas, placement honored (HTTP)" as *u8)
112
113 // R6 (neg): POST /build tier|block incomplete -> refused
114 let n6: i64 = e_send(req, e_post(req, "/build" as *u8, "tier|block\nfooter|only a footer\n" as *u8), resp, 262143)
115 ok = 0; if ehas(resp,n6,"Refused" as *u8)==1 { ok=1 }
116 rows=rows+1; pass=pass+erow(6, ok, "POST /build incomplete -> refused (publish-gate holds over HTTP)" as *u8)
117
118 // R7 (neg): POST /build tier|guided hostile -> escaped over HTTP
119 let n7: i64 = e_send(req, e_post(req, "/build" as *u8, "tier|guided\nbrand|<script>alert(1)</script>\ncta|C\ncta_href|#c\nheadline|H\nsub|s\nsearch|/s\ncard_title|A\ncard_body|b\nstep1|1\nstep2|2\ntrust|T\nfooter|F\n" as *u8), resp, 262143)
120 ok = 0; if ehas(resp,n7,"<script>alert(1)" as *u8)==0 { if ehas(resp,n7,"<script>alert(1)" as *u8)==1 { ok=1 } }
121 rows=rows+1; pass=pass+erow(7, ok, "POST /build hostile field -> escaped (HTTP)" as *u8)
122
123 __syscall(129, pid, 9, 0, 0, 0, 0) // kill(pid, SIGKILL) -- rv64 kill=129; raw x86 62 is an RV64 KEY translated to lseek(8) (debt idx 2277)
124
125 ew("NX-STUDIO-E2E-GATE rows=" as *u8); let rb: *u8=sys_mmap(8); rb[0]=(48+rows) as u8; sys_write(1,rb,1); ew(" pass=" as *u8); let pb: *u8=sys_mmap(8); pb[0]=(48+pass) as u8; sys_write(1,pb,1); ew("\n" as *u8)
126 if pass == rows {
127 let line: *u8 = sys_mmap(128); var lo: i64 = ecat(line, 0, "CMSGATE row=nx_studio_e2e capability-studio-http-e2e rows=8 pass=8 verdict=PASS\n" as *u8)
128 let gf: i64 = sys_openat_append("knowledge/status/cms_gate.log" as *u8, 0x1a4)
129 if gf >= 0 { sys_write(gf, line, lo); sys_close(gf) }
130 ew("NX-STUDIO-E2E-GATE verdict=PASS -- capability-adaptive studio works end-to-end over real HTTP\n" as *u8)
131 sys_exit(0); return 0
132 }
133 ew("NX-STUDIO-E2E-GATE verdict=FAIL -- NOT recorded (no fake-green)\n" as *u8)
134 sys_exit(1); return 1
135}