code wiki / _hdl_build / _wiki_cite_live_gate.nx
_wiki_cite_live_gate.nx source
↩ module page · 264 lines · 14066 B
1// _wiki_cite_live_gate.nx -- THE LIVE INLINE-CITE-CARD GATE (served output).
2//
3// Re-proves, from a REAL run (never a fabricated GREEN), that the anti-pushout
4// [[cite:<cid>]] supporting-source cards render LIVE (UNESCAPED) in the SERVED
5// wiki page -- judged on the actually-served (post-markdown) HTTP bytes, driven
6// through the SAME render body the daemon forks (nx_wiki_doc_handle_cp, the
7// cite-prefix-injectable form of nx_wiki_doc_handle).
8//
9// THE BUG THIS KILLS (the SAME shape as the escaped-[[wikilink]] bug): the cite
10// pass USED to expand [[cite:<cid>]] -> <details class="nx-cite"> card HTML
11// BEFORE markdown ran, so markdown_inline html-escaped the '<','>' to <,>
12// and the SERVED bytes were <details... (dead escaped text), NOT a real
13// expandable card. The old cite gates "passed" only because they asserted the
14// substring in the PRE-markdown cite-render buffer -- a MEASUREMENT ARTIFACT;
15// the served output was escaped. FIX (mirrors the wikilink split): leave the
16// literal [[cite:<cid>]] token in the body, render markdown, then a POST-markdown
17// cite pass replaces each token with the card HTML emitted RAW (never escaped).
18//
19// SEED a FRESH per-run content-addressed archive prefix (empty each run =>
20// idempotent, Rule 10; never the production WAR_PREFIX) with:
21// S1 HOSTABLE (CC_BY) content "ALPHA-INLINE-EVIDENCE-777"
22// S2 PROPRIETARY (NOT host) content "SECRET-NOHOST-888"
23// SEED a doc store with ONE page whose body cites BOTH:
24// "... [[cite:<cid_S1>]] ... [[cite:<cid_S2>]] ..."
25// RENDER it via nx_wiki_doc_handle_cp(..., prefix) and judge the SERVED HTML:
26//
27// card_live the served HTML contains a LIVE "<details class=\"nx-cite\""
28// (NOT "<details") AND "ALPHA-INLINE-EVIDENCE-777" sits INSIDE
29// that card (after the details-open + the card body div).
30// not_escaped the served HTML does NOT contain "<details" ANYWHERE (no
31// dead html-escaped card leaked through).
32// liar_kill "SECRET-NOHOST-888" appears NOWHERE in the served HTML (the
33// proprietary source's bytes are suppressed), while a link +
34// license-note for S2 IS present (nx-cite-link + the note text).
35//
36// Verdict line (stdout + knowledge/status/wiki_cite_live_gate.log):
37// WIKICITELIVE card_live=<0|1> not_escaped=<0|1> liar_kill=<0|1> verdict=GREEN|RED
38//
39// Pure NishiLang, NO SQL, NO .sh/.py/.js, no new .tsv/.conf. nx_sites_daemon
40// UNTOUCHED. Imports the served handler under test (which transitively pulls the
41// cite-render + license + archive + seg_store chain, each spliced ONCE by the
42// resolver's module-identity dedup). license_tier: ORIGINAL
43import "nx_syscalls.nx"
44import "wiki/nx_wiki_index_builder.nx"
45import "wiki/nx_wiki_doc_handler.nx"
46import "wiki/nx_wiki_cite_render.nx"
47import "wiki/nx_artifact_store.nx"
48
49const WCL_LOG: *u8 = "knowledge/status/wiki_cite_live_gate.log"
50const WCL_RESP_CAP: i64 = 2097152 // 2 MiB served-response buffer
51const WCL_SCAN_CAP: i64 = 64 // archive segment-scan cap
52
53// ===== io helpers (mirror _wiki_frontend_gate.nx) ============================
54func wcl_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
55func wcl_n(fd: i64, v: i64) -> i64 {
56 let bb: *u8 = sys_mmap(28); var m: i64 = v
57 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
58 let t: *u8 = sys_mmap(28); var k: i64 = 0
59 if m == 0 { t[0] = 48 as u8; k = 1 }
60 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
61 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
62 sys_write(fd, bb, k); return 0
63}
64func wcl_w2(lfd: i64, s: *u8) -> i64 { wcl_w(1, s); if lfd >= 0 { wcl_w(lfd, s) } return 0 }
65func wcl_n2(lfd: i64, v: i64) -> i64 { wcl_n(1, v); if lfd >= 0 { wcl_n(lfd, v) } return 0 }
66func wcl_p(s: *u8) -> i64 { wcl_w(1, s); return 0 }
67func wcl_pn(v: i64) -> i64 { wcl_n(1, v); return 0 }
68func wcl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
69
70func wcl_cat(dst: *u8, off: i64, s: *u8) -> i64 {
71 var i: i64 = 0
72 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 }
73 return off + i
74}
75func wcl_catn(dst: *u8, off: i64, v: i64) -> i64 {
76 var m: i64 = v; var o: i64 = off
77 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m }
78 let t: *u8 = sys_mmap(28); var k: i64 = 0
79 if m == 0 { t[0] = 48 as u8; k = 1 }
80 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
81 var i: i64 = 0; while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
82 return o + k
83}
84
85// ===== GROUND-TRUTH SUBSTRING SEARCH (judge on the SERVED HTML) ==============
86func wcl_find(hay: *u8, hn: i64, needle: *u8) -> i64 {
87 let nn: i64 = wcl_slen(needle)
88 if nn == 0 { return 0 - 1 }
89 if nn > hn { return 0 - 1 }
90 var i: i64 = 0
91 let last: i64 = hn - nn
92 while i <= last {
93 var j: i64 = 0
94 var eq: i64 = 1
95 while j < nn {
96 if eq == 1 { if hay[i + j] != needle[j] { eq = 0 } }
97 j = j + 1
98 }
99 if eq == 1 { return i }
100 i = i + 1
101 }
102 return 0 - 1
103}
104func wcl_has(hay: *u8, hn: i64, needle: *u8) -> i64 {
105 if wcl_find(hay, hn, needle) >= 0 { return 1 }
106 return 0
107}
108
109func main() -> i64 {
110 wcl_p("WIKICITELIVE-GATE: start (served [[cite]] card LIVE/unescaped + liar-kill)\n" as *u8)
111
112 // ===== FRESH per-run archive prefix => empty archive each run (idempotent) ==
113 // Never the production WAR_PREFIX; the handler reads THIS prefix via the
114 // cite-prefix-injectable nx_wiki_doc_handle_cp, so we exercise the SERVED path
115 // without touching production data.
116 let prefix: *u8 = sys_mmap(256)
117 var po: i64 = 0
118 po = wcl_cat(prefix, po, "knowledge/store/wikiarchive-citelivegate-" as *u8)
119 po = wcl_catn(prefix, po, sys_now_realtime_sec())
120 po = wcl_cat(prefix, po, "-" as *u8)
121 prefix[po] = 0 as u8
122 wcl_p(" store prefix = " as *u8); wcl_p(prefix); wcl_p("\n" as *u8)
123
124 // distinctive content strings the gate searches for in the SERVED HTML
125 let evidence: *u8 = "ALPHA-INLINE-EVIDENCE-777" as *u8
126 let secret: *u8 = "SECRET-NOHOST-888" as *u8
127
128 // ===== SEED S1 (CC-BY, hostable) ==========================================
129 let s1_slug: *u8 = "src-live1" as *u8
130 let s1_body: *u8 = "Supporting evidence: ALPHA-INLINE-EVIDENCE-777 (full text of the hostable cited source).\n" as *u8
131 let cid_s1: *u8 = sys_mmap(80)
132 let w1: *i64 = ss_begin()
133 let r1: i64 = war_archive_page(w1, s1_slug, s1_body, wcl_slen(s1_body), cid_s1)
134 let c1: i64 = ss_commit(prefix, w1, 0)
135 let lset1: i64 = nx_wiki_license_set(prefix, cid_s1, NXLIC_CC_BY, 1)
136 wcl_p(" S1 (CC-BY) archive_rc=" as *u8); wcl_pn(r1); wcl_p(" commit=" as *u8); wcl_pn(c1)
137 wcl_p(" cid=" as *u8); wcl_p(cid_s1); wcl_p(" license_get=" as *u8); wcl_pn(nx_wiki_license_get(prefix, cid_s1)); wcl_p("\n" as *u8)
138
139 // ===== SEED S2 (PROPRIETARY, NOT hostable) ================================
140 let s2_slug: *u8 = "src-live2" as *u8
141 let s2_body: *u8 = "Confidential: SECRET-NOHOST-888 must never be inlined without a license.\n" as *u8
142 let cid_s2: *u8 = sys_mmap(80)
143 let w2: *i64 = ss_begin()
144 let r2: i64 = war_archive_page(w2, s2_slug, s2_body, wcl_slen(s2_body), cid_s2)
145 let c2: i64 = ss_commit(prefix, w2, 2)
146 let lset2: i64 = nx_wiki_license_set(prefix, cid_s2, NXLIC_PROPRIETARY, 3)
147 wcl_p(" S2 (PROPRIETARY) archive_rc=" as *u8); wcl_pn(r2); wcl_p(" commit=" as *u8); wcl_pn(c2)
148 wcl_p(" cid=" as *u8); wcl_p(cid_s2); wcl_p(" license_get=" as *u8); wcl_pn(nx_wiki_license_get(prefix, cid_s2))
149 wcl_p(" hostable=" as *u8); wcl_pn(nx_wiki_license_hostable(nx_wiki_license_get(prefix, cid_s2))); wcl_p("\n" as *u8)
150
151 // SANITY: prove S2's secret bytes ARE retrievable from the archive, so the
152 // absence-from-HTML below is a real suppression, not an archiving miss.
153 let pps: *i64 = sys_mmap(16) as *i64
154 let s2got: i64 = war_get_by_cid(prefix, cid_s2, pps, WCL_SCAN_CAP)
155 var s2_in_store: i64 = 0
156 if s2got > 0 { if wcl_has(pps[0] as *u8, s2got, secret) == 1 { s2_in_store = 1 } }
157 wcl_p(" S2 secret-in-store=" as *u8); wcl_pn(s2_in_store); wcl_p(" (archive readback len=" as *u8); wcl_pn(s2got); wcl_p(")\n" as *u8)
158
159 // ===== SEED a doc store with ONE page citing BOTH S1 and S2 ===============
160 let store: *NxWikiDocStore = sys_mmap(2048) as *NxWikiDocStore
161 let rc_init: i64 = nx_wiki_doc_store_init(store, 16, 8192, 8192, 65536)
162 wcl_p(" store_init rc=" as *u8); wcl_pn(rc_init); wcl_p("\n" as *u8)
163
164 // body: a markdown heading + a paragraph citing S1 (hostable) and S2 (proprietary).
165 let pg: *u8 = sys_mmap(1024)
166 var g: i64 = 0
167 g = wcl_cat(pg, g, "# Cite Live Page\n\nHostable source read in place: [[cite:" as *u8)
168 g = wcl_cat(pg, g, cid_s1)
169 g = wcl_cat(pg, g, "]].\n\nProprietary source (link only): [[cite:" as *u8)
170 g = wcl_cat(pg, g, cid_s2)
171 g = wcl_cat(pg, g, "]].\n" as *u8)
172 pg[g] = 0 as u8
173 let pg_rid: i64 = nx_wiki_doc_store_add(store,
174 "Cite Live Page" as *u8, 14, "/wiki/cite-live" as *u8, 15, pg, g)
175 wcl_p(" seeded page rowid=" as *u8); wcl_pn(pg_rid); wcl_p(" body_len=" as *u8); wcl_pn(g)
176 wcl_p(" doc_count=" as *u8); wcl_pn(nx_wiki_doc_store_count(store)); wcl_p("\n" as *u8)
177
178 // ===== RENDER via the REAL served handler (cite-prefix-injectable) ========
179 // artifact_store = 0: a null artifact store is a graceful no-op (no pipeline
180 // banner) per Cardinal 14 -- the page still renders. cite_prefix = our fresh
181 // per-run archive prefix, so the cite post-pass resolves OUR S1/S2.
182 let url: *u8 = "/wiki/cite-live" as *u8
183 let url_n: i64 = 15
184 let resp: *u8 = sys_mmap(WCL_RESP_CAP)
185 let resp_n: *i64 = (sys_mmap(8)) as *i64
186 resp_n[0] = 0
187 let h_rc: i64 = nx_wiki_doc_handle_cp(store, 0 as *NxArtifactStore, url, url_n,
188 resp, WCL_RESP_CAP, resp_n, prefix)
189 let hn: i64 = resp_n[0]
190 wcl_p(" handle rc=" as *u8); wcl_pn(h_rc); wcl_p(" resp_len=" as *u8); wcl_pn(hn); wcl_p("\n" as *u8)
191
192 // ---- card_live: a LIVE "<details class=\"nx-cite\"" present AND the evidence
193 // sits INSIDE it (after the details-open AND the card-body div). The card is
194 // emitted RAW by the POST-markdown cite pass, so it is real markup not text.
195 // NOTE: "nx-cite-body" ALSO appears in the <head> CSS (.nx-cite-body{...}), so
196 // we scope the card-body + evidence search to the region AT/AFTER the
197 // details-open (the card's OWN body div), not the whole document.
198 var card_live: i64 = 0
199 let det_at: i64 = wcl_find(resp, hn, "<details class=\"nx-cite\"" as *u8)
200 var body_at: i64 = 0 - 1
201 var ev_at: i64 = 0 - 1
202 if det_at >= 0 {
203 let tail: *u8 = (resp as i64 + det_at) as *u8
204 let tail_n: i64 = hn - det_at
205 let rb: i64 = wcl_find(tail, tail_n, "nx-cite-body" as *u8)
206 if rb >= 0 { body_at = det_at + rb }
207 let re: i64 = wcl_find(tail, tail_n, evidence)
208 if re >= 0 { ev_at = det_at + re }
209 }
210 if det_at >= 0 { if body_at > det_at { if ev_at > body_at { card_live = 1 } } }
211 wcl_p(" card_live: details@" as *u8); wcl_pn(det_at); wcl_p(" card-body@" as *u8); wcl_pn(body_at)
212 wcl_p(" evidence@" as *u8); wcl_pn(ev_at); wcl_p(" -> card_live=" as *u8); wcl_pn(card_live); wcl_p("\n" as *u8)
213
214 // ---- not_escaped: NO "<details" anywhere (no dead html-escaped card) ----
215 var not_escaped: i64 = 1
216 let esc_at: i64 = wcl_find(resp, hn, "<details" as *u8)
217 if esc_at >= 0 { not_escaped = 0 }
218 wcl_p(" not_escaped: <details@" as *u8); wcl_pn(esc_at)
219 wcl_p(" (-1=absent=GOOD) -> not_escaped=" as *u8); wcl_pn(not_escaped); wcl_p("\n" as *u8)
220
221 // ---- liar_kill: the proprietary secret bytes appear NOWHERE in the served
222 // HTML, AND a link + license-note for S2 IS present (suppressed, not labeled).
223 var liar_kill: i64 = 0
224 let leak_at: i64 = wcl_find(resp, hn, secret)
225 let link_at: i64 = wcl_find(resp, hn, "nx-cite-link" as *u8)
226 let note_at: i64 = wcl_find(resp, hn, "licensing restricts inline hosting" as *u8)
227 if leak_at < 0 { if link_at >= 0 { if note_at >= 0 { liar_kill = 1 } } }
228 wcl_p(" liar_kill: SECRET_LEAK@" as *u8); wcl_pn(leak_at); wcl_p(" (-1=absent=GOOD)")
229 wcl_p(" link@" as *u8); wcl_pn(link_at); wcl_p(" note@" as *u8); wcl_pn(note_at)
230 wcl_p(" -> liar_kill=" as *u8); wcl_pn(liar_kill); wcl_p("\n" as *u8)
231
232 // ===== EVIDENCE: echo a served-HTML chunk around the two cards for judging ==
233 // Locate the first card and print a window from there (so the inline card +
234 // the suppressed link are both visible to the human reader).
235 wcl_p(" ---- served HTML window around the cite cards ----\n" as *u8)
236 var win_start: i64 = 0
237 if det_at >= 0 { win_start = det_at - 80 }
238 if win_start < 0 { win_start = 0 }
239 var win_len: i64 = hn - win_start
240 if win_len > 1400 { win_len = 1400 }
241 let win_ptr: *u8 = (resp as i64 + win_start) as *u8
242 sys_write(1, win_ptr, win_len)
243 wcl_p("\n ---- /served window ----\n" as *u8)
244
245 // ===== VERDICT =====
246 var green: i64 = 1
247 if card_live != 1 { green = 0 }
248 if not_escaped != 1 { green = 0 }
249 if liar_kill != 1 { green = 0 }
250 // belt-and-suspenders: the secret must truly have been in the store, so the
251 // suppression we measured was a real liar-kill (not an archiving miss).
252 if s2_in_store != 1 { green = 0 }
253
254 let lfd: i64 = sys_openat_append(WCL_LOG, 420)
255 wcl_w2(lfd, "WIKICITELIVE card_live=" as *u8); wcl_n2(lfd, card_live)
256 wcl_w2(lfd, " not_escaped=" as *u8); wcl_n2(lfd, not_escaped)
257 wcl_w2(lfd, " liar_kill=" as *u8); wcl_n2(lfd, liar_kill)
258 if green == 1 { wcl_w2(lfd, " verdict=GREEN\n" as *u8) } else { wcl_w2(lfd, " verdict=RED\n" as *u8) }
259 if lfd >= 0 { sys_close(lfd) }
260
261 if green == 1 { sys_exit(0); return 0 }
262 sys_exit(1)
263 return 1
264}