code wiki / _hdl_build / nx_domain_map_gate.nx
nx_domain_map_gate.nx source
↩ module page · 127 lines · 8858 B
1// nx_domain_map_gate.nx -- GATE for nx_domain_map (the /compare/webscraping R8 contracts dm_scan + dm_soft404).
2// Network-free: every parser and the fingerprint classifier are PURE and are tested here on runtime fixtures; the
3// live composition is proven by running the organ on a real domain (its summary line carries the partition and the
4// fetch counts). Accept rule pre-declared on the board: a 200 that matches the not-found fingerprint is SOFT404, a
5// 200 with a different title or a different length is LIVE (the false-positive control), a host whose fingerprint
6// is a real 404 can never produce SOFT404; robots paths are mined without wildcards; crt.sh hosts are deduplicated,
7// lowercased, wildcard-stripped and kept under the domain only.
8// license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_domain_map.nx"
11import "nx_gate_verdict.nx"
12
13const DG_CAP: i64 = 8192
14const DG_SLOT: i64 = 256
15const DG_MAX: i64 = 32
16
17func dg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
18func dg_slot(b: *u8, i: i64) -> *u8 { return (b as i64 + i * DG_SLOT) as *u8 }
19
20func main() -> i64 {
21 gv_head("=== nx_domain_map gate (soft-404 fingerprint, robots path mining, crt.sh hosts, sitemap recursion; network-free) ===" as *u8)
22 let ctr: *i64 = gv_ctr()
23 dm_load_conf()
24 gv_puts(" conf_src=" as *u8); if dm_conf_src_g == 1 { gv_puts("file" as *u8) } else { gv_puts("defaults" as *u8) }
25 gv_puts(" max_fetches=" as *u8); gv_num(dm_max_fetches_g); gv_puts(" tol_permil=" as *u8); gv_num(dm_tol_g); gv_puts("\n" as *u8)
26
27 // ---- T1 title hash ----
28 let h1: *u8 = "<html><head><TITLE>Not Found</TITLE></head><body>x</body></html>" as *u8
29 let h2: *u8 = "<html><head><title>Not Found</title></head><body>yy</body></html>" as *u8
30 let h3: *u8 = "<html><head><title>Docs</title></head><body>real</body></html>" as *u8
31 let h4: *u8 = "<html><body>no title here</body></html>" as *u8
32 var t1: i64 = 0
33 if dm_title_hash(h1, dg_len(h1)) == dm_title_hash(h2, dg_len(h2)) { if dm_title_hash(h1, dg_len(h1)) != dm_title_hash(h3, dg_len(h3)) { if dm_title_hash(h4, dg_len(h4)) == 0 { t1 = 1 } } }
34 gv_check("T1 title hash: case-insensitive tag, equal titles equal, different titles differ, no title -> 0" as *u8, t1, ctr)
35
36 // ---- T2 soft-404 classifier ----
37 let fpt: i64 = dm_title_hash(h1, dg_len(h1))
38 let doct: i64 = dm_title_hash(h3, dg_len(h3))
39 var t2: i64 = 1
40 if dm_soft404_classify(200, 1000, fpt, 200, 1050, fpt, 100) != 1 { t2 = 0 } // same status, title, +5 pct -> SOFT404
41 if dm_soft404_classify(200, 1000, fpt, 200, 1200, fpt, 100) != 0 { t2 = 0 } // +20 pct -> LIVE
42 if dm_soft404_classify(200, 1000, fpt, 200, 1000, doct, 100) != 0 { t2 = 0 } // different title -> LIVE
43 if dm_soft404_classify(404, 1000, fpt, 200, 1000, fpt, 100) != 0 { t2 = 0 } // real-404 host -> never SOFT404
44 if dm_soft404_classify(200, 1000, fpt, 404, 1000, fpt, 100) != 0 { t2 = 0 } // a real 404 probe is not soft
45 if dm_soft404_classify(200, 0, 0, 200, 0, 0, 100) != 1 { t2 = 0 } // empty fingerprint, empty probe -> soft (nothing served either way)
46 gv_check("T2 soft-404 classifier: status + title + length tolerance, real-404 hosts exempt (6 KATs)" as *u8, t2, ctr)
47 var bad: i64 = dm_soft404_classify(200, 1000, fpt, 200, 1020, fpt, 100)
48 var good: i64 = dm_soft404_classify(200, 1000, fpt, 200, 5400, doct, 100)
49 gv_bite("T3 BITE: fires on the not-found page wearing a 200, silent on a real docs page" as *u8, bad, good, ctr)
50
51 // ---- T3b the dm_soft404 contract: abstains before a fingerprint exists, then classifies from the run's own ----
52 var t3b: i64 = 0
53 dm_fp_taken_g = 0
54 if dm_soft404(200, 1000, fpt) == 0 - 1 {
55 dm_fp_taken_g = 1; dm_fp_status_g = 200; dm_fp_len_g = 1000; dm_fp_title_g = fpt
56 if dm_soft404(200, 1020, fpt) == 1 { if dm_soft404(200, 1020, doct) == 0 { t3b = 1 } }
57 }
58 gv_check("T3b dm_soft404 returns -1 (UNOBSERVABLE) before a fingerprint exists, then classifies from the run's own fingerprint" as *u8, t3b, ctr)
59
60 // ---- T4 robots path mining ----
61 let rob: *u8 = "User-agent: *\nDisallow: /private/\nAllow: /api/public\nDisallow: /*.pdf$\nDisallow: /\nDisallow: /private/\nSitemap: https://a.org/sitemap.xml\nDisallow: /admin\n" as *u8
62 let paths: *u8 = sys_mmap(DG_SLOT * DG_MAX)
63 let np: i64 = dm_robots_paths(rob, dg_len(rob), paths, DG_SLOT, DG_MAX)
64 gv_puts(" robots paths=" as *u8); gv_num(np); gv_puts("\n" as *u8)
65 var t4: i64 = 0
66 if np == 3 { if dm_streq(dg_slot(paths, 0), "/private/" as *u8) == 1 { if dm_streq(dg_slot(paths, 1), "/api/public" as *u8) == 1 { if dm_streq(dg_slot(paths, 2), "/admin" as *u8) == 1 { t4 = 1 } } } }
67 gv_check("T4 robots mining: Allow and Disallow paths kept, wildcard and root rules skipped, duplicates collapsed, Sitemap line ignored" as *u8, t4, ctr)
68
69 // ---- T5 crt.sh hosts ----
70 let js: *u8 = "[{\"issuer_name\":\"x\",\"name_value\":\"*.a.org\\nAPI.a.org\\nwww.a.org\"},{\"name_value\":\"evil.b.org\\nnota-a.org\"},{\"name_value\":\"www.a.org\"},{\"name_value\":\"a.org\"}]" as *u8
71 let hosts: *u8 = sys_mmap(DG_SLOT * DG_MAX)
72 let ov: *i64 = sys_mmap(16) as *i64
73 ov[0] = 0
74 let nh: i64 = dm_crt_hosts(js, dg_len(js), "a.org" as *u8, hosts, DG_SLOT, DG_MAX, ov)
75 gv_puts(" crt hosts=" as *u8); gv_num(nh); gv_puts(":" as *u8)
76 var hi: i64 = 0
77 while hi < nh { gv_puts(" " as *u8); gv_puts(dg_slot(hosts, hi)); hi = hi + 1 }
78 gv_puts("\n" as *u8)
79 var t5: i64 = 0
80 if nh == 3 { if dm_streq(dg_slot(hosts, 0), "a.org" as *u8) == 1 { if dm_streq(dg_slot(hosts, 1), "api.a.org" as *u8) == 1 { if dm_streq(dg_slot(hosts, 2), "www.a.org" as *u8) == 1 { t5 = 1 } } } }
81 gv_check("T5 crt.sh: wildcard stripped, lowercased, deduplicated, foreign and lookalike hosts refused (nota-a.org)" as *u8, t5, ctr)
82 var t5b: i64 = 0
83 ov[0] = 0
84 let nh2: i64 = dm_crt_hosts(js, dg_len(js), "a.org" as *u8, hosts, DG_SLOT, 2, ov)
85 if nh2 == 2 { if ov[0] == 2 { t5b = 1 } }
86 gv_check("T5b the host cap COUNTS each refused occurrence (www.a.org twice past the cap -> oversize=2); repeats of kept hosts are neither" as *u8, t5b, ctr)
87
88 // ---- T6 gzip magic + sitemap recursion classification (the estate's own sm_is_subsitemap) ----
89 let gz: *u8 = sys_mmap(16)
90 gz[0] = 31 as u8; gz[1] = 139 as u8; gz[2] = 8 as u8
91 var t6: i64 = 0
92 if dm_is_gzip(gz, 3) == 1 { if dm_is_gzip("<?xml" as *u8, 5) == 0 { if dm_is_gzip(gz, 1) == 0 { t6 = 1 } } }
93 gv_check("T6 gzip magic detected, XML and a 1-byte body are not gzip" as *u8, t6, ctr)
94 var t7: i64 = 0
95 if sm_is_subsitemap("https://a.org/sitemap-posts.xml.gz" as *u8, 34) == 1 { if sm_is_subsitemap("https://a.org/post/1" as *u8, 20) == 0 { t7 = 1 } }
96 gv_check("T7 a .xml.gz loc is a sub-sitemap to recurse into, a page loc is a url row" as *u8, t7, ctr)
97
98 // ---- T8 the nonce path and the url builder ----
99 let p: *u8 = sys_mmap(DG_SLOT)
100 let pl: i64 = dm_nonce_path(p, "a.org" as *u8)
101 let p2: *u8 = sys_mmap(DG_SLOT)
102 dm_nonce_path(p2, "b.org" as *u8)
103 let u: *u8 = sys_mmap(DG_SLOT)
104 let ul: i64 = dm_url(u, "a.org" as *u8, "/docs" as *u8)
105 var t8: i64 = 0
106 if pl > 20 { if (p[0] as i64) == 47 { if dm_streq(p, p2) == 0 { if dm_streq(u, "https://a.org/docs" as *u8) == 1 { if ul == 18 { t8 = 1 } } } } }
107 gv_check("T8 the fingerprint path is per-domain and cannot collide with a real path; url builder is exact" as *u8, t8, ctr)
108
109 // ---- T8b a budget refusal is OUR decision, never the host's: status box carries DM_STATUS_BUDGET ----
110 let sb: *i64 = sys_mmap(16) as *i64
111 dm_max_fetches_g = 0
112 let fb: *u8 = sys_mmap(DG_SLOT)
113 let nfb: i64 = dm_fetch("https://a.org/x" as *u8, 0 as *TrustStore, fb, DG_SLOT, sb)
114 var t8b: i64 = 0
115 if nfb == 0 { if sb[0] == DM_STATUS_BUDGET { t8b = 1 } }
116 gv_check("T8b past the fetch budget dm_fetch refuses without a network call and marks the status box BUDGET, not UNREACHABLE" as *u8, t8b, ctr)
117 dm_load_conf()
118
119 // ---- T9 partition arithmetic on the counters (the summary line's own rule) ----
120 dm_rows_total_g = 0; dm_rows_robots_g = 0; dm_rows_sitemap_g = 0; dm_rows_feed_g = 0; dm_rows_wayback_g = 0; dm_rows_crt_g = 0; dm_rows_probe_g = 0
121 dm_outfd_g = 0
122 var t9: i64 = 0
123 if dm_row("probe" as *u8, "path" as *u8, DM_V_LIVE, "/x" as *u8, 2) == 0 { if dm_rows_total_g == 0 { t9 = 1 } }
124 gv_check("T9 with no output file open, a row is refused (0) and not counted -- rows are what was WRITTEN" as *u8, t9, ctr)
125
126 return gv_verdict("DOMAIN-MAP-GATE" as *u8, ctr, "soft-404 fingerprint classifies by status+title+length with real-404 hosts exempt; robots paths, crt.sh hosts, gzip and sitemap recursion parse as declared; caps count what they refuse" as *u8)
127}