nx_aimode_read.nx source
↩ module page · 175 lines · 9071 B
1// nx_aimode_read.nx -- CLI for BR50: read a Google AI Mode share link as its answer text.
2// nx_aimode_read <share-url> [out-path]
3// Writes knowledge/fetched/aimode_<id>.answer.txt (or <out-path>):
4// # nx_aimode_read v1
5// # share_url=<the url the operator pasted -- the CITED url>
6// # final_url=<the /search url the share resolved to>
7// # fetched_at=<epoch>
8// # citations=<N>
9// <blank>
10// <answer text>
11// <blank>
12// ## Citations (<N>) -- the server-rendered /url? beacon references (opaque Google redirect tokens)
13// <one per line>
14// then appends a provenance row prov|<epoch>|<share url>|<mirror>|<sha256>|<bytes>|<hops> to the shared
15// fetch_provenance.jrnl (the CITED url is the SHARE url, never an internal endpoint -- refs-gate contract).
16// Refuses BY NAME: REFUSED-CONSENT-WALL / REFUSED-SIGNIN / REFUSED-NO-ANSWER / REFUSED-EMPTY-BODY (+fetch).
17// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
18import "nx_syscalls.nx"
19import "nx_x509_trust_store.nx"
20import "nx_trust_store_load_from_certdata.nx"
21import "nx_aimode_lib.nx"
22import "nx_sha256.nx"
23import "nx_atomic_rewrite.nx"
24
25const R_CERTCAP: i64 = 4194304
26const R_OUTCAP: i64 = 8388608
27const R_CITECAP: i64 = 262144
28const R_URLCAP: i64 = 16384
29const R_DOCCAP: i64 = 8912896
30
31func pw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
32func pe(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(2, s, n); return 0 }
33func pn(v: i64) -> i64 {
34 let b: *u8 = sys_mmap(24); var m: i64 = v; var i: i64 = 23
35 if m == 0 { i = i - 1; b[i] = 48 as u8 }
36 while m > 0 { i = i - 1; b[i] = (48 + (m % 10)) as u8; m = m / 10 }
37 sys_write(1, (b as i64 + i) as *u8, 23 - i); return 0
38}
39func rcat(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } return o }
40func rcatn(dst: *u8, o: i64, v: i64) -> i64 {
41 if v == 0 { dst[o] = 48 as u8; return o + 1 }
42 let t: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0
43 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
44 var j: i64 = k - 1
45 while j >= 0 { dst[o] = t[j]; o = o + 1; j = j - 1 }
46 return o
47}
48func rslen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
49
50// extract the share id after the LAST "aimode/" into out (id chars: alnum, - and _). Returns len.
51func r_share_id(url: *u8, out: *u8) -> i64 {
52 let ul: i64 = rslen(url)
53 let mark: *u8 = "aimode/" as *u8
54 var mpos: i64 = 0 - 1
55 var i: i64 = 0
56 while i + 7 <= ul {
57 var m: i64 = 1; var j: i64 = 0
58 while j < 7 { if (url[i+j]&0xff) != (mark[j]&0xff) { m = 0; j = 7 } else { j = j + 1 } }
59 if m == 1 { mpos = i + 7 }
60 i = i + 1
61 }
62 if mpos < 0 { out[0] = 0 as u8; return 0 }
63 var o: i64 = 0
64 var k: i64 = mpos
65 while k < ul {
66 let c: i64 = url[k] & 0xff
67 var ok: i64 = 0
68 if c >= 48 { if c <= 57 { ok = 1 } }
69 if c >= 65 { if c <= 90 { ok = 1 } }
70 if c >= 97 { if c <= 122 { ok = 1 } }
71 if c == 45 { ok = 1 }
72 if c == 95 { ok = 1 }
73 if ok == 0 { k = ul } else { out[o] = c as u8; o = o + 1; k = k + 1 }
74 }
75 out[o] = 0 as u8
76 return o
77}
78
79func r_hex32(dst: *u8, o: i64, digest: *u8) -> i64 {
80 var i: i64 = 0
81 while i < 32 {
82 let b: i64 = digest[i] & 0xff
83 let hi: i64 = (b >> 4) & 15
84 let lo: i64 = b & 15
85 if hi < 10 { dst[o] = (48 + hi) as u8 } else { dst[o] = (87 + hi) as u8 }
86 if lo < 10 { dst[o+1] = (48 + lo) as u8 } else { dst[o+1] = (87 + lo) as u8 }
87 o = o + 2; i = i + 1
88 }
89 return o
90}
91
92func main(argc: i64, argv: *i64) -> i64 {
93 if argc < 2 {
94 pe("usage: nx_aimode_read <share-url> [out-path]\n" as *u8)
95 sys_exit(2); return 2
96 }
97 let share_url: *u8 = argv[1] as *u8
98 let id: *u8 = sys_mmap(256); let idl: i64 = r_share_id(share_url, id)
99
100 // out path
101 let path: *u8 = sys_mmap(1024)
102 var pp: i64 = 0
103 if argc >= 3 { pp = rcat(path, 0, argv[2] as *u8) }
104 else {
105 pp = rcat(path, 0, "knowledge/fetched/aimode_" as *u8)
106 if idl > 0 { var q: i64 = 0; while id[q] != (0 as u8) { path[pp] = id[q]; pp = pp + 1; q = q + 1 } }
107 else { pp = rcat(path, pp, "unknown" as *u8) }
108 pp = rcat(path, pp, ".answer.txt" as *u8)
109 }
110 path[pp] = 0 as u8
111
112 let store: *TrustStore = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, R_CERTCAP) as *TrustStore
113 if (store as i64) == 0 { pe("REFUSED-FETCH: trust store load failed\n" as *u8); sys_exit(14); return 14 }
114
115 let out: *u8 = sys_mmap(R_OUTCAP)
116 let cites: *u8 = sys_mmap(R_CITECAP)
117 let finalu: *u8 = sys_mmap(R_URLCAP)
118 let ncit: *i64 = (sys_mmap(8)) as *i64
119 let tlen: *i64 = (sys_mmap(8)) as *i64
120
121 let rc: i64 = br_share_read(share_url, store, out, R_OUTCAP, cites, R_CITECAP, finalu, R_URLCAP, ncit, tlen, 1)
122 if rc != AM_OK {
123 if rc == AM_CONSENT { pe("REFUSED-CONSENT-WALL: a Google consent wall stands between the share link and its answer\n" as *u8); sys_exit(11); return 11 }
124 if rc == AM_SIGNIN { pe("REFUSED-SIGNIN: the share link demands a signed-in session\n" as *u8); sys_exit(10); return 10 }
125 if rc == AM_EMPTY { pe("REFUSED-EMPTY-BODY: a pass returned status but an empty body\n" as *u8); sys_exit(13); return 13 }
126 if rc == AM_NOCONT { pe("REFUSED-NO-ANSWER: the warm search document carried no /async/folwr continuation and no inline answer\n" as *u8); sys_exit(12); return 12 }
127 if rc == AM_NO_ANSWER { pe("REFUSED-NO-ANSWER: the continuation returned a shell with no answer text\n" as *u8); sys_exit(12); return 12 }
128 if rc == AM_NOFINAL { pe("REFUSED-NO-ANSWER: the share link never resolved to a search document (redirects did not settle)\n" as *u8); sys_exit(15); return 15 }
129 pe("REFUSED-FETCH: could not fetch a pass over sovereign TLS\n" as *u8); sys_exit(14); return 14
130 }
131
132 // build the output document: header, answer text, citation list.
133 let doc: *u8 = sys_mmap(R_DOCCAP)
134 var d: i64 = rcat(doc, 0, "# nx_aimode_read v1\n# share_url=" as *u8)
135 d = rcat(doc, d, share_url); doc[d] = 10 as u8; d = d + 1
136 d = rcat(doc, d, "# final_url=" as *u8); d = rcat(doc, d, finalu); doc[d] = 10 as u8; d = d + 1
137 d = rcat(doc, d, "# fetched_at=" as *u8); d = rcatn(doc, d, sys_now_realtime_sec()); doc[d] = 10 as u8; d = d + 1
138 d = rcat(doc, d, "# extraction_coverage=unknown; complete_conversation_not_established\n" as *u8)
139 d = rcat(doc, d, "# citations=" as *u8); d = rcatn(doc, d, ncit[0]); doc[d] = 10 as u8; d = d + 1
140 doc[d] = 10 as u8; d = d + 1
141 var a: i64 = 0
142 while a < tlen[0] { doc[d] = out[a]; d = d + 1; a = a + 1 }
143 doc[d] = 10 as u8; d = d + 1; doc[d] = 10 as u8; d = d + 1
144 d = rcat(doc, d, "## Citations (" as *u8); d = rcatn(doc, d, ncit[0]); d = rcat(doc, d, ") -- server-rendered /url? beacon references (opaque Google redirect tokens)\n" as *u8)
145 var cl: i64 = 0; while cites[cl] != (0 as u8) { doc[d] = cites[cl]; d = d + 1; cl = cl + 1 }
146
147 let write_rc: i64 = atomic_rewrite_checked(path, doc, d)
148 if write_rc != 0 {
149 if write_rc == AR_CHECK_UNCERTAIN {
150 pe("AIMODE-OUTPUT-COMMIT-UNCERTAIN: rename occurred but durability/readback failed; inspect output before retry\n" as *u8)
151 sys_exit(17); return 17
152 }
153 pe("REFUSED-OUTPUT-WRITE: checked atomic output failed before verified commit; shared writer reason=" as *u8)
154 pn(0 - write_rc); pe("\n" as *u8)
155 sys_exit(16); return 16
156 }
157
158 // provenance: the CITED url is the SHARE url (never the internal /search or /async endpoint).
159 let digest: *u8 = sys_mmap(32)
160 sha256_digest(doc, d, digest)
161 let row: *u8 = sys_mmap(4096)
162 var rp: i64 = rcat(row, 0, "prov|" as *u8)
163 rp = rcatn(row, rp, sys_now_realtime_sec()); row[rp] = 124 as u8; rp = rp + 1
164 rp = rcat(row, rp, share_url); row[rp] = 124 as u8; rp = rp + 1
165 rp = rcat(row, rp, path); row[rp] = 124 as u8; rp = rp + 1
166 rp = r_hex32(row, rp, digest); row[rp] = 124 as u8; rp = rp + 1
167 rp = rcatn(row, rp, d); row[rp] = 124 as u8; rp = rp + 1
168 rp = rcatn(row, rp, 2); row[rp] = 10 as u8; rp = rp + 1 // hops: share.google's measured double redirect
169 let jfd: i64 = sys_openat_append("knowledge/status/fetch_provenance.jrnl" as *u8, MODE_0644)
170 if jfd >= 0 { let prov_written:i64=sys_write(jfd,row,rp);let prov_closed:i64=sys_close(jfd);if prov_written!=rp||prov_closed!=0{pe("AIMODE-PROVENANCE-UNWRITTEN: incomplete append/close; output exists but provenance requires inspection\n" as *u8)} }
171 else { pe("AIMODE-PROVENANCE-UNWRITTEN: cannot append fetch_provenance.jrnl -- this mirror reads UNPROVEN to the refs gate\n" as *u8) }
172
173 pw("NX-AIMODE-READ OK id=" as *u8); pw(id); pw(" citations=" as *u8); pn(ncit[0]); pw(" text_bytes=" as *u8); pn(tlen[0]); pw(" file=" as *u8); pw(path); pw("\n" as *u8)
174 sys_exit(0); return 0
175}