code wiki / _hdl_build / nx_manga_add_gate.nx
nx_manga_add_gate.nx source
↩ module page · 94 lines · 5421 B
1import "nx_gate_grow.nx"
2import "nx_gate_gn.nx"
3import "nx_gate_base.nx"
4import "nx_gate_read.nx"
5// nx_manga_add_gate.nx -- SOVEREIGN referee for the /api/manga/add PURE logic (no network: the download itself is
6// nx_manga_get, gated + live-proven separately). Proves the form parse + url validation + slug derivation + the
7// fail-closed responses. chdir /tmp.
8// T1 ma_form_val: url + title parsed from a urlencoded body (%3A/%2F decode, '+' -> space, & boundary)
9// T2 ma_url_ok: https:// ok, http:// ok, ftp:// rejected, javascript: rejected, embedded-space rejected
10// T3 ma_derive_slug: sanitized title + 8-hex url fnv suffix; SAME url+title -> SAME slug (deterministic);
11// different url -> different slug
12// T4 ma_handle_add NEG: no body -> 400 ; bad url -> 400 (no fork attempted)
13// T5 ma_handle_add: valid body but nx_manga_get.elf ABSENT -> 502 (truth = cbx.json on disk, never exit code)
14// GREEN iff 5/5. license_tier: ORIGINAL expect_exit: 0
15import "nx_syscalls.nx"
16import "nx_manga_add.nx"
17
18func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
19func g_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]==(0 as u8){return 1} return 0 }
20func g_has(hay: *u8, n: i64, needle: *u8) -> i64 {
21 var nn: i64 = 0; while needle[nn] != (0 as u8) { nn = nn + 1 }
22 if nn == 0 { return 0 }
23 var i: i64 = 0
24 while i + nn <= n { var m: i64 = 1; var j: i64 = 0; while j < nn { if (hay[i + j] as i64) != (needle[j] as i64) { m = 0; j = nn } else { j = j + 1 } } if m == 1 { return 1 } i = i + 1 }
25 return 0
26}
27func g_unlink(path: *u8) -> i64 { __syscall(263, 0 - 100, path, 0, 0, 0, 0); return 0 }
28
29// call ma_handle_add with a body; capture response via a file fd. Returns response bytes.
30func g_add(body: *u8, blen: i64, ukey: *u8, out: *u8, cap: i64) -> i64 {
31 let rp: *u8 = "ma_rsp.tmp" as *u8
32 g_unlink(rp)
33 let fd: i64 = sys_openat_wr("ma_rsp.tmp" as *u8, 0x1a4)
34 if fd < 0 { return 0 - 1 }
35 // ma_handle_add reads body at req+body_off; give body_off=0 so req==body
36 ma_handle_add(fd, body, 0, blen, ukey)
37 return g_read("ma_rsp.tmp" as *u8, out, cap)
38}
39
40func main() -> i64 {
41 gw("manga-add SOVEREIGN gate (form parse + url validate + slug derive + fail-closed)\n" as *u8)
42 if sys_chdir("/tmp" as *u8) != 0 { gw("CHDIR /tmp FAIL\n" as *u8); sys_exit(1) }
43 var pass: i64 = 0
44
45 // ---- T1 form parse ----
46 let body: *u8 = "url=https%3A%2F%2Fx.com%2Fch1&title=Cool+Manga" as *u8
47 let u: *u8 = sys_mmap(4096); ma_form_val(body, g_slen(body), "url" as *u8, u, 4096)
48 let t: *u8 = sys_mmap(512); ma_form_val(body, g_slen(body), "title" as *u8, t, 512)
49 var t1: i64 = 0
50 if g_streq(u, "https://x.com/ch1" as *u8) == 1 { if g_streq(t, "Cool Manga" as *u8) == 1 { t1 = 1 } }
51 gw(" url=" as *u8); gw(u); gw(" title=" as *u8); gw(t); gw("\n" as *u8)
52 pass = pass + grow("T1 ma_form_val: %-decode + '+'->space + & boundary\x00" as *u8, t1)
53
54 // ---- T2 url validation ----
55 var t2: i64 = 0
56 if ma_url_ok("https://a.b/c" as *u8, 13) == 1 { if ma_url_ok("http://a.b/c" as *u8, 12) == 1 {
57 if ma_url_ok("ftp://a.b/c" as *u8, 11) == 0 { if ma_url_ok("javascript:alert(1)" as *u8, 19) == 0 {
58 if ma_url_ok("https://a.b/ c" as *u8, 14) == 0 { t2 = 1 } // embedded space
59 } }
60 } }
61 pass = pass + grow("T2 ma_url_ok: https/http ok, ftp/js/space rejected\x00" as *u8, t2)
62
63 // ---- T3 slug derivation ----
64 let s1: *u8 = sys_mmap(128); ma_derive_slug("Cool Manga!!" as *u8, 12, "https://x.com/ch1" as *u8, 17, s1)
65 let s2: *u8 = sys_mmap(128); ma_derive_slug("Cool Manga!!" as *u8, 12, "https://x.com/ch1" as *u8, 17, s2)
66 let s3: *u8 = sys_mmap(128); ma_derive_slug("Cool Manga!!" as *u8, 12, "https://x.com/ch2" as *u8, 17, s3)
67 var t3: i64 = 0
68 if g_streq(s1, s2) == 1 { if g_streq(s1, s3) == 0 { if g_has(s1, g_slen(s1), "cool_manga" as *u8) == 1 { t3 = 1 } } }
69 gw(" slug1=" as *u8); gw(s1); gw(" slug3=" as *u8); gw(s3); gw("\n" as *u8)
70 pass = pass + grow("T3 ma_derive_slug: sanitized + deterministic + url-unique\x00" as *u8, t3)
71
72 // ---- T4 fail-closed responses ----
73 let rsp: *u8 = sys_mmap(4096)
74 let kA: *u8 = "elder_11223344" as *u8
75 var t4: i64 = 0
76 var rn: i64 = g_add("" as *u8, 0, kA, rsp, 4096)
77 if g_has(rsp, rn, "HTTP/1.1 400" as *u8) == 1 {
78 rn = g_add("url=notaurl&title=x" as *u8, 19, kA, rsp, 4096)
79 if g_has(rsp, rn, "HTTP/1.1 400" as *u8) == 1 { t4 = 1 }
80 }
81 pass = pass + grow("T4 NEG: no body -> 400 ; bad url -> 400\x00" as *u8, t4)
82
83 // ---- T5 valid body but downloader elf ABSENT -> 502 (truth = cbx.json on disk) ----
84 g_unlink("_offc/nx_manga_get.elf" as *u8)
85 var t5: i64 = 0
86 let vbody: *u8 = "url=https%3A%2F%2Fexample.com%2Fnope&title=Ghost" as *u8
87 rn = g_add(vbody, g_slen(vbody), kA, rsp, 4096)
88 if g_has(rsp, rn, "HTTP/1.1 502" as *u8) == 1 { if g_has(rsp, rn, "no pages" as *u8) == 1 { t5 = 1 } }
89 pass = pass + grow("T5 downloader absent -> 502 no-pages (on-disk truth, no fake green)\x00" as *u8, t5)
90
91 gw("pass=" as *u8); gn(pass); gw("/5\n" as *u8)
92 if pass == 5 { gw("verdict=GREEN (add endpoint: form/url/slug pure logic + fail-closed 400/502, on-disk truth)\n" as *u8); sys_exit(0); return 0 }
93 gw("verdict=RED\n" as *u8); sys_exit(1); return 1
94}