code wiki / (root) / nx_office_serve.nx

nx_office_serve.nx source

↩ module page · 3769 lines · 237163 B

1// nx_office_serve.nx -- NISHI OFFICE v1, the PRODUCT surface over the gated format organs (operator 2026-07-09: 2// "we need to build our own nishi office"). Until now the suite was organs + scattered sample pages; THIS organ is 3// the office: a zero-JS web app where a family member CREATES, EDITS, VERSIONS, PREVIEWS and DOWNLOADS real 4// documents / spreadsheets / decks. Every save = a NEW version (v1,v2,...) -- nothing is ever overwritten; that 5// additive never-lose history is the suite's one measured exceed, now surfaced as the product spine. 6// Engines (forked ELFs, the gated organs): doc = _offc/nx_docx.elf writerich (H/B/I/P + T pipe-cells) ? 7// sheet = _offc/nx_xlsx.elf fromtsv (TSV grid, =SUM/AVERAGE/MIN/MAX/COUNT formulas) ? deck = _offc/nx_pptx.elf 8// fromspec (S title / B bullet). Preview = each organ's own html mode. Honest v1 scope: SPEC editors (plain 9// textarea round-trip), NOT WYSIWYG -- that is the named next rung, along with co-edit (CRDT) and in-app AI. 10// Layout under <root>/: index.txt (append-only name\tkind registry) + <name>/manifest.txt (append-only 11// v<N>\t<kind>\t<usec> lines) + <name>/v<N>/{spec.txt, file.<ext>, preview.html}. 12// PURE CORE (no main): of_handle (request -> response), of_read_req/of_write_all (fd shells), of_selftest (the 13// offline gate body). Consumers: _hdl_build/nx_office_gate (offline gate) + _hdl_build/nx_office_daemon (accept 14// loop, port 8030). Same discipline as nx_relate_serve. license_tier: ORIGINAL 15import "nx_tool_run.nx" 16import "nx_gate_verdict.nx" // D001: the selftest's teeth inherit the shared verdict base (gv_check / gv_verdict) 17import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 18import "nx_itoa_lib.nx" // shared integer emitter: nxi_out (fd) and nxi_buf (NUL-free buffer form) 19import "nx_rebac.nx" // the shared ReBAC plane: doc ownership + sharing are rb_ tuples (doc:<name> owner|viewer|editor) 20import "nx_http_client.nx" // loopback POST to our own sovereign LLM seat (:11434) for in-app AI drafting 21import "nx_multipart.nx" // RFC 7578 multipart/form-data parser (the docportal's proven <input type=file> path) -- LP1 import 22import "nx_sign_ceremony_lib.nx" // UETA consent-gated signing over the hash-chained audit + sealed certificate -- LP4 sign-from-version 23 24// office authz store. The office daemon runs as ELDERWESTO (its reconcile cron), NOT root -- so the store must be 25// in the elderwesto-writable cwd (nishihost/officeauthz_*), NOT the root-owned knowledge/status/ (which relate, 26// running as root, created). Tuples live OUTSIDE office/ so they never render as documents. A doc with NO owner 27// tuple stays PUBLIC (legacy/demo -> non-breaking). 28const OF_AUTHZ: *u8 = "officeauthz_" 29const OF_RELATE: *u8 = "knowledge/status/relate_" 30 31func p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 32// MIGRATED to the shared emitter (debt 1785557603): the old body mmapped TWO buffers per call 33// (LSB-first digits + a reverse buffer) and freed neither. nxi_out is the ONE shim, always balanced. 34func pn(v: i64) -> i64 { nxi_out(v); return 0 } 35func of_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 36func of_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } return off + i } 37func of_catc(dst: *u8, off: i64, code: i64) -> i64 { dst[off] = code as u8; return off + 1 } 38// MIGRATED to nxi_buf, the NUL-FREE shared form. The old body mmapped a reverse buffer per call and 39// never freed it -- and this function has 60 CALL SITES, so the leak was per-call in a long-lived 40// server. nxi_buf is MSB-first (allocates nothing) and, unlike ccz_cat_num, writes NO byte past the 41// returned offset -- gate tooth T15 proves that difference by biting. 42func of_catn(dst: *u8, off: i64, v: i64) -> i64 { return nxi_buf(dst, off, v) } 43func of_seq(a: *u8, b: *u8) -> i64 { 44 var i: i64 = 0 45 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 46 if b[i] != (0 as u8) { return 0 } 47 return 1 48} 49func of_starts(s: *u8, pfx: *u8) -> i64 { var i: i64 = 0; while pfx[i] != (0 as u8) { if s[i] != pfx[i] { return 0 } i = i + 1 } return 1 } 50func of_memhas(buf: *u8, n: i64, needle: *u8) -> i64 { 51 let nl: i64 = of_slen(needle) 52 if nl == 0 { return 0 } 53 var i: i64 = 0 54 while i + nl <= n { 55 var k: i64 = 0; var hit: i64 = 1 56 while k < nl { if buf[i+k] != needle[k] { hit = 0; k = nl } else { k = k + 1 } } 57 if hit == 1 { return 1 } 58 i = i + 1 59 } 60 return 0 61} 62// escape & < > while appending a NUL-terminated string (safe for html text and textarea content) 63func of_esc(dst: *u8, off: i64, s: *u8) -> i64 { 64 var o: i64 = off; var i: i64 = 0 65 while s[i] != (0 as u8) { 66 let c: i64 = s[i] as i64 67 if c == 38 { o = of_cat(dst, o, "&amp;" as *u8) } else { 68 if c == 60 { o = of_cat(dst, o, "&lt;" as *u8) } else { 69 if c == 62 { o = of_cat(dst, o, "&gt;" as *u8) } else { dst[o] = s[i]; o = o + 1 } } } 70 i = i + 1 71 } 72 return o 73} 74func of_hexval(c: i64) -> i64 { 75 if c >= 48 { if c <= 57 { return c - 48 } } 76 if c >= 65 { if c <= 70 { return c - 55 } } 77 if c >= 97 { if c <= 102 { return c - 87 } } 78 return 0 79} 80// urldecode form value for key from body (handles + and %XX). proven pattern (nx_relate_serve). 81func of_form_get(body: *u8, blen: i64, key: *u8, out: *u8, cap: i64) -> i64 { 82 let kl: i64 = of_slen(key) 83 var i: i64 = 0 84 while i < blen { 85 var atk: i64 = 0 86 if i == 0 { atk = 1 } else { if body[i-1] == (38 as u8) { atk = 1 } } 87 if atk == 1 { 88 var m: i64 = 1; var j: i64 = 0 89 while j < kl { if i + j >= blen { m = 0; j = kl } else { if body[i+j] != key[j] { m = 0; j = kl } else { j = j + 1 } } } 90 if m == 1 { if i + kl < blen { if body[i+kl] == (61 as u8) { 91 var q: i64 = i + kl + 1; var t: i64 = 0 92 var go: i64 = 1 93 while go == 1 { 94 if q >= blen { go = 0 } else { 95 let c: i64 = body[q] as i64 96 if c == 38 { go = 0 } else { 97 var ch: i64 = c 98 if c == 43 { ch = 32 } 99 if c == 37 { if q + 2 < blen { ch = of_hexval(body[q+1] as i64) * 16 + of_hexval(body[q+2] as i64); q = q + 2 } } 100 if t < cap - 1 { out[t] = ch as u8; t = t + 1 } 101 q = q + 1 102 } 103 } 104 } 105 out[t] = 0 as u8; return t 106 } } } 107 } 108 i = i + 1 109 } 110 out[0] = 0 as u8; return 0 111} 112func of_write_all(fd: i64, buf: *u8, n: i64) -> i64 { 113 var w: i64 = 0 114 while w < n { let k: i64 = sys_write(fd, (buf as i64 + w) as *u8, n - w); if k <= 0 { return 0 - 1 } w = w + k } 115 return 0 116} 117// read ONE full HTTP request: headers until CRLFCRLF plus Content-Length body. proven pattern. 118func of_read_req(fd: i64, buf: *u8, cap: i64) -> i64 { 119 var n: i64 = 0 120 var hdr_end: i64 = 0 - 1 121 var want: i64 = 0 - 1 122 var go: i64 = 1 123 while go == 1 { 124 if n >= cap - 1 { go = 0 } else { 125 let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n) 126 if r <= 0 { go = 0 } else { 127 n = n + r 128 if hdr_end < 0 { 129 var i: i64 = 0 130 while i + 3 < n { 131 if buf[i] == (13 as u8) { if buf[i+1] == (10 as u8) { if buf[i+2] == (13 as u8) { if buf[i+3] == (10 as u8) { hdr_end = i + 4; i = n } } } } 132 i = i + 1 133 } 134 if hdr_end >= 0 { 135 var cl: i64 = 0 - 1 136 let key: *u8 = "Content-Length:" as *u8 137 let kl: i64 = 15 138 var j: i64 = 0 139 while j + kl < hdr_end { 140 var m: i64 = 1 141 var q: i64 = 0 142 while q < kl { if buf[j+q] != key[q] { m = 0; q = kl } else { q = q + 1 } } 143 if m == 1 { 144 var v: i64 = 0 145 var t: i64 = j + kl 146 while t < hdr_end { 147 let c: i64 = buf[t] as i64 148 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } 149 if c == 13 { t = hdr_end } 150 t = t + 1 151 } 152 cl = v 153 j = hdr_end 154 } 155 j = j + 1 156 } 157 if cl < 0 { want = hdr_end } else { want = hdr_end + cl } 158 } 159 } 160 if want >= 0 { if n >= want { go = 0 } } 161 } 162 } 163 } 164 return n 165} 166func of_read_file(path: *u8, buf: *u8, cap: i64) -> i64 { 167 let fd: i64 = sys_openat_rd(path) 168 if fd < 0 { return 0 - 1 } 169 var tot: i64 = 0 170 while tot < cap { let r: i64 = sys_read(fd, (buf as i64 + tot) as *u8, cap - tot); if r <= 0 { break } tot = tot + r } 171 sys_close(fd) 172 return tot 173} 174func of_write_file(path: *u8, buf: *u8, n: i64) -> i64 { 175 let fd: i64 = sys_openat_wr(path, 420) 176 if fd < 0 { return 0 - 1 } 177 let rc: i64 = of_write_all(fd, buf, n) 178 sys_close(fd) 179 return rc 180} 181// extract a header value (key like "Origin:") from the header region; trims one leading space; stops at CR. 182func of_hdr_get(req: *u8, reqlen: i64, key: *u8, out: *u8, cap: i64) -> i64 { 183 out[0] = 0 as u8 184 var he: i64 = reqlen 185 var i: i64 = 0 186 while i + 3 < reqlen { 187 if req[i] == (13 as u8) { if req[i+1] == (10 as u8) { if req[i+2] == (13 as u8) { if req[i+3] == (10 as u8) { he = i; i = reqlen } } } } 188 i = i + 1 189 } 190 let kl: i64 = of_slen(key) 191 var j: i64 = 0 192 while j + kl < he { 193 var m: i64 = 1 194 var q: i64 = 0 195 while q < kl { if req[j+q] != key[q] { m = 0; q = kl } else { q = q + 1 } } 196 if m == 1 { 197 var t: i64 = j + kl 198 if req[t] == (32 as u8) { t = t + 1 } 199 var o: i64 = 0 200 while t < he { if req[t] == (13 as u8) { t = he } else { if o < cap - 1 { out[o] = req[t]; o = o + 1 } t = t + 1 } } 201 out[o] = 0 as u8 202 return o 203 } 204 j = j + 1 205 } 206 return 0 207} 208func of_atoi(s: *u8) -> i64 { 209 var v: i64 = 0 210 var i: i64 = 0 211 while s[i] != (0 as u8) { 212 let d: i64 = (s[i] as i64) - 48 213 if d >= 0 { if d <= 9 { v = v * 10 + d } } 214 i = i + 1 215 } 216 return v 217} 218 219// ---- domain: names, kinds, layout ---- 220func of_name_ok(name: *u8) -> i64 { 221 var i: i64 = 0 222 while name[i] != (0 as u8) { 223 let c: i64 = name[i] as i64 224 var ok: i64 = 0 225 if c >= 97 { if c <= 122 { ok = 1 } } 226 if c >= 48 { if c <= 57 { ok = 1 } } 227 if c == 45 { ok = 1 } 228 if ok == 0 { return 0 } 229 i = i + 1 230 } 231 if i < 1 { return 0 } 232 if i > 40 { return 0 } 233 return 1 234} 235func of_kind_idx(kind: *u8) -> i64 { 236 if of_seq(kind, "doc" as *u8) == 1 { return 0 } 237 if of_seq(kind, "sheet" as *u8) == 1 { return 1 } 238 if of_seq(kind, "deck" as *u8) == 1 { return 2 } 239 return 0 - 1 240} 241func of_ext(k: i64) -> *u8 { 242 if k == 0 { return "docx" as *u8 } 243 if k == 1 { return "xlsx" as *u8 } 244 return "pptx" as *u8 245} 246func of_elf(k: i64) -> *u8 { 247 if k == 0 { return "_offc/nx_docx.elf" as *u8 } 248 if k == 1 { return "_offc/nx_xlsx.elf" as *u8 } 249 return "_offc/nx_pptx.elf" as *u8 250} 251func of_ct(k: i64) -> *u8 { 252 if k == 0 { return "application/vnd.openxmlformats-officedocument.wordprocessingml.document" as *u8 } 253 if k == 1 { return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" as *u8 } 254 return "application/vnd.openxmlformats-officedocument.presentationml.presentation" as *u8 255} 256func of_kind_name(k: i64) -> *u8 { 257 if k == 0 { return "doc" as *u8 } 258 if k == 1 { return "sheet" as *u8 } 259 return "deck" as *u8 260} 261// versions so far for <name> (0 = does not exist); kind of the file copied into kindout. 262func of_manifest_count(root: *u8, name: *u8, kindout: *u8, kcap: i64) -> i64 { 263 kindout[0] = 0 as u8 264 let mp: *u8 = sys_mmap(512) 265 var o: i64 = of_cat(mp, 0, root); o = of_cat(mp, o, "/" as *u8); o = of_cat(mp, o, name); o = of_cat(mp, o, "/manifest.txt" as *u8); mp[o] = 0 as u8 266 let buf: *u8 = sys_mmap(65536) 267 let n: i64 = of_read_file(mp, buf, 65536) 268 if n <= 0 { return 0 } 269 var lines: i64 = 0 270 var i: i64 = 0 271 while i < n { if buf[i] == (10 as u8) { lines = lines + 1 } i = i + 1 } 272 // kind = field 2 of the FIRST line (v<N> \t kind \t usec) 273 var t: i64 = 0 274 while t < n { if buf[t] == (9 as u8) { break } t = t + 1 } 275 t = t + 1 276 var ko: i64 = 0 277 while t < n { if buf[t] == (9 as u8) { t = n } else { if buf[t] == (10 as u8) { t = n } else { if ko < kcap - 1 { kindout[ko] = buf[t]; ko = ko + 1 } t = t + 1 } } } 278 kindout[ko] = 0 as u8 279 return lines 280} 281// build "<root>/<name>/v<N>" into out, return offset 282func of_vdir(root: *u8, name: *u8, vn: i64, out: *u8) -> i64 { 283 var o: i64 = of_cat(out, 0, root); o = of_cat(out, o, "/" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "/v" as *u8); o = of_catn(out, o, vn) 284 out[o] = 0 as u8 285 return o 286} 287// append one line to an append-only file (creates if missing) 288func of_append_line(path: *u8, line: *u8, n: i64) -> i64 { 289 let fd: i64 = sys_openat_append(path, 420) 290 if fd < 0 { return 0 - 1 } 291 let rc: i64 = of_write_all(fd, line, n) 292 sys_close(fd) 293 return rc 294} 295// ---- PER-DOCUMENT LOCK (2026-08-19, measured regression from the fork-per-request daemon) -------------------- 296// of_save / of_import / of_sign_version are read-modify-writes (manifest count -> mkdir v<N+1> -> append row; 297// sign.head read -> chain -> write) that the old serial accept loop protected BY ACCIDENT. Fork-per-request removed 298// that accident and the race was MEASURED live: 4 concurrent creates of one name -> TWO v1 manifest rows (one 299// writer's artifacts silently clobbered) + two 500s. The lock is per document ("<root>/<name>.lock", the estate's 300// <prefix>plock idiom), taken in thin wrappers so every caller -- /save, /restore, /import, /sign -- inherits it 301// and no body return path can leak it. flock is per open file description, and no body takes this lock again, so 302// self-deadlock is impossible by construction. Fail-open on OPEN failure (loud, behaviour = the pre-lock daemon): 303// wrong in the direction of doing nothing new. 304const OF_LOCK_EX: i64 = 2 305const OF_LOCK_UN: i64 = 8 306const OF_LOCKMODE: i64 = 420 307func of_doc_lock(root: *u8, name: *u8) -> i64 { 308 let lkp: *u8 = sys_mmap(600) 309 var o: i64 = of_cat(lkp, 0, root) 310 o = of_cat(lkp, o, "/" as *u8) 311 o = of_cat(lkp, o, name) 312 o = of_cat(lkp, o, ".lock" as *u8) 313 lkp[o] = 0 as u8 314 let fd: i64 = sys_openat_append(lkp, OF_LOCKMODE) 315 sys_munmap(lkp, 600) 316 if fd < 0 { p("OF-DOC-LOCK open-failed (proceeding UNLOCKED, the pre-lock behaviour) 317" as *u8); return 0 - 1 } 318 sys_flock(fd, OF_LOCK_EX) 319 return fd 320} 321func of_doc_unlock(fd: i64) -> i64 { 322 if fd < 0 { return 0 } 323 sys_flock(fd, OF_LOCK_UN) 324 sys_close(fd) 325 return 0 326} 327// SAVE: validate -> new version dir -> spec -> fork the format organ (artifact) -> fork html (preview) -> 328// register in manifest (+ index on v1). auto=1 (background autosave) tags the manifest line with an ADDITIVE 329// 4th field "auto" -- older parsers read fields 1-3 unchanged. Returns the new version N, or a LOUD negative: 330// -1 invalid name/kind/spec -2 kind mismatch with existing file -3 organ build failed -4 preview failed 331func of_save(root: *u8, base: *u8, name: *u8, kind: *u8, spec: *u8, sl: i64, auto: i64) -> i64 { 332 if of_name_ok(name) == 0 { return 0 - 1 } 333 sys_mkdir(root, 493) 334 let lk: i64 = of_doc_lock(root, name) 335 let rc: i64 = of_save_body(root, base, name, kind, spec, sl, auto) 336 of_doc_unlock(lk) 337 return rc 338} 339func of_save_body(root: *u8, base: *u8, name: *u8, kind: *u8, spec: *u8, sl: i64, auto: i64) -> i64 { 340 if of_name_ok(name) == 0 { return 0 - 1 } 341 let k: i64 = of_kind_idx(kind) 342 if k < 0 { return 0 - 1 } 343 if sl <= 0 { return 0 - 1 } 344 if sl > 131072 { return 0 - 1 } 345 sys_mkdir(root, 493) 346 let nd: *u8 = sys_mmap(512) 347 var no: i64 = of_cat(nd, 0, root); no = of_cat(nd, no, "/" as *u8); no = of_cat(nd, no, name); nd[no] = 0 as u8 348 sys_mkdir(nd, 493) 349 let kbuf: *u8 = sys_mmap(64) 350 let cur: i64 = of_manifest_count(root, name, kbuf, 64) 351 if cur > 0 { if of_seq(kbuf, kind) == 0 { return 0 - 2 } } 352 let vn: i64 = cur + 1 353 let vd: *u8 = sys_mmap(512) 354 of_vdir(root, name, vn, vd) 355 sys_mkdir(vd, 493) 356 let specp: *u8 = sys_mmap(600) 357 var so: i64 = of_cat(specp, 0, vd); so = of_cat(specp, so, "/spec.txt" as *u8); specp[so] = 0 as u8 358 if of_write_file(specp, spec, sl) != 0 { return 0 - 3 } 359 let artp: *u8 = sys_mmap(600) 360 let ext: *u8 = of_ext(k) 361 var ao: i64 = of_cat(artp, 0, vd); ao = of_cat(artp, ao, "/file." as *u8); ao = of_cat(artp, ao, ext); artp[ao] = 0 as u8 362 let prevp: *u8 = sys_mmap(600) 363 var po: i64 = of_cat(prevp, 0, vd); po = of_cat(prevp, po, "/preview.html" as *u8); prevp[po] = 0 as u8 364 let dlu: *u8 = sys_mmap(600) 365 var du: i64 = of_cat(dlu, 0, base); du = of_cat(dlu, du, "/file/" as *u8); du = of_cat(dlu, du, name); du = of_cat(dlu, du, "/v" as *u8); du = of_catn(dlu, du, vn); dlu[du] = 0 as u8 366 let elf: *u8 = of_elf(k) 367 let av: *i64 = sys_mmap(8 * 8) as *i64 368 av[0] = elf as i64 369 if k == 0 { av[1] = "writerich" as *u8 as i64; av[2] = artp as i64; av[3] = specp as i64 } else { 370 if k == 1 { av[1] = "fromtsv" as *u8 as i64; av[2] = specp as i64; av[3] = artp as i64 } else { 371 av[1] = "fromspec" as *u8 as i64; av[2] = specp as i64; av[3] = artp as i64 } } 372 av[4] = 0 373 let capbuf: *u8 = sys_mmap(65536) 374 let ol: *i64 = sys_mmap(16) as *i64 375 let rc: i64 = tr_run_capture(elf, av, capbuf, 65536, ol) 376 if rc != 0 { return 0 - 3 } 377 let av2: *i64 = sys_mmap(8 * 8) as *i64 378 av2[0] = elf as i64 379 av2[1] = "html" as *u8 as i64 380 av2[2] = artp as i64 381 av2[3] = prevp as i64 382 av2[4] = dlu as i64 383 av2[5] = 0 384 let rc2: i64 = tr_run_capture(elf, av2, capbuf, 65536, ol) 385 if rc2 != 0 { return 0 - 4 } 386 let mp: *u8 = sys_mmap(600) 387 var mo: i64 = of_cat(mp, 0, nd); mo = of_cat(mp, mo, "/manifest.txt" as *u8); mp[mo] = 0 as u8 388 let line: *u8 = sys_mmap(256) 389 var lo: i64 = of_cat(line, 0, "v" as *u8); lo = of_catn(line, lo, vn); lo = of_catc(line, lo, 9); lo = of_cat(line, lo, kind); lo = of_catc(line, lo, 9); lo = of_catn(line, lo, sys_now_us()) 390 if auto == 1 { lo = of_catc(line, lo, 9); lo = of_cat(line, lo, "auto" as *u8) } 391 lo = of_catc(line, lo, 10) 392 if of_append_line(mp, line, lo) != 0 { return 0 - 3 } 393 if vn == 1 { 394 let ip: *u8 = sys_mmap(600) 395 var io: i64 = of_cat(ip, 0, root); io = of_cat(ip, io, "/index.txt" as *u8); ip[io] = 0 as u8 396 let il: *u8 = sys_mmap(256) 397 var ilo: i64 = of_cat(il, 0, name); ilo = of_catc(il, ilo, 9); ilo = of_cat(il, ilo, kind); ilo = of_catc(il, ilo, 10) 398 of_append_line(ip, il, ilo) 399 } 400 return vn 401} 402 403// ---- pages (zero-JS, sovereign styling, no hash-colors) ---- 404func of_css(out: *u8, off: i64) -> i64 { 405 // CSS custom properties drive light/dark so the JS theme toggle is one class flip (:root.dark / :root.light); 406 // system preference wins unless the user chose. U-axes rung: app shell, card grid, thumbnails, transitions. 407 var o: i64 = off 408 // canonical --nx-color tokens (fleet bar / ui_rubric) with local shorthand ALIASES so every existing 409 // var(--bg)-style usage keeps working; dark redefines only the canon and the aliases follow. 410 o = of_cat(out, o, "<style>:root{--nx-color-bg:rgb(244,246,251);--nx-color-ink:rgb(23,25,35);--nx-color-surface:rgb(255,255,255);--nx-color-line:rgb(224,227,237);--nx-color-muted:rgb(107,112,128);--nx-color-accent:rgb(41,84,164);--nx-radius:12px;--bg:var(--nx-color-bg);--fg:var(--nx-color-ink);--card:var(--nx-color-surface);--line:var(--nx-color-line);--muted:var(--nx-color-muted);--acc:var(--nx-color-accent);--accfg:rgb(255,255,255);--accbg:rgb(234,240,252);--soft:rgb(249,250,253);--sh:rgba(20,28,55,0.07);--sh2:rgba(20,28,55,0.16);--mark:rgb(255,233,148);--good:rgb(21,110,48)}\n" as *u8) 411 o = of_cat(out, o, "@media(prefers-color-scheme:dark){:root:not(.light){--nx-color-bg:rgb(13,14,19);--nx-color-ink:rgb(226,228,238);--nx-color-surface:rgb(21,23,31);--nx-color-line:rgb(42,45,58);--nx-color-muted:rgb(146,150,165);--nx-color-accent:rgb(124,163,235);--accfg:rgb(16,22,38);--accbg:rgb(31,39,60);--soft:rgb(17,19,26);--sh:rgba(0,0,0,0.4);--sh2:rgba(0,0,0,0.55);--mark:rgb(126,100,14);--good:rgb(89,196,124)}}\n" as *u8) 412 o = of_cat(out, o, ":root.dark{--nx-color-bg:rgb(13,14,19);--nx-color-ink:rgb(226,228,238);--nx-color-surface:rgb(21,23,31);--nx-color-line:rgb(42,45,58);--nx-color-muted:rgb(146,150,165);--nx-color-accent:rgb(124,163,235);--accfg:rgb(16,22,38);--accbg:rgb(31,39,60);--soft:rgb(17,19,26);--sh:rgba(0,0,0,0.4);--sh2:rgba(0,0,0,0.55);--mark:rgb(126,100,14);--good:rgb(89,196,124)}\n" as *u8) 413 o = of_cat(out, o, "*{box-sizing:border-box}html{scroll-behavior:smooth}body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;background:var(--bg);color:var(--fg);margin:0;line-height:1.55;font-size:clamp(15px,1vw + 12px,17px)}\n" as *u8) 414 o = of_cat(out, o, "a{color:var(--acc)}h1{margin:0 0 2px;font-size:clamp(20px,2.6vw,26px)}h2{font-size:clamp(15px,1.8vw,18px);margin:22px 0 4px}.sub{color:var(--muted);margin:0 0 14px}\n" as *u8) 415 // fleet-bar accessibility + motion: skip-link, visible keyboard focus, entrance rise (stagger via 416 // nth-child), and a reduced-motion kill-switch. 417 o = of_cat(out, o, ".skip-link{position:absolute;left:-999px;top:0;background:var(--acc);color:rgb(255,255,255);padding:12px 16px;z-index:99;border-radius:0 0 8px 0}.skip-link:focus{left:0}\n" as *u8) 418 o = of_cat(out, o, ":focus-visible{outline:2px solid var(--acc);outline-offset:2px}.top input[type=text]:focus-visible{outline:0}\n" as *u8) 419 o = of_cat(out, o, "@keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}main>*{animation:rise .35s ease both}main>*:nth-child(2){animation-delay:.06s}main>*:nth-child(3){animation-delay:.12s}main>*:nth-child(4){animation-delay:.18s}\n" as *u8) 420 o = of_cat(out, o, "@media(prefers-reduced-motion:reduce){main>*{animation:none}.fcard,button,.chips a,.top input[type=text],.thm{transition:none}html{scroll-behavior:auto}}\n" as *u8) 421 o = of_cat(out, o, ".top{position:sticky;top:0;z-index:9;padding:5px 20px;background:var(--card);border-bottom:1px solid var(--line);box-shadow:0 1px 10px var(--sh)}.top nav{display:flex;align-items:center;gap:12px;max-width:1200px;margin:0 auto}\n" as *u8) 422 o = of_cat(out, o, ".logo{width:30px;height:30px;min-width:30px;border-radius:8px;background:linear-gradient(135deg,rgb(64,110,200),rgb(35,66,132))}\n" as *u8) 423 o = of_cat(out, o, "a.bname{display:inline-flex;align-items:center;gap:9px;min-height:44px;font-weight:700;font-size:1.02rem;color:var(--fg);text-decoration:none;white-space:nowrap}.top form{flex:1;max-width:560px;margin:0}\n" as *u8) 424 o = of_cat(out, o, ".top input[type=text]{width:100%;border:1px solid var(--line);border-radius:20px;padding:8px 16px;font-size:.93rem;background:var(--soft);color:var(--fg);transition:border-color .15s,box-shadow .15s}.top input[type=text]:focus{outline:0;border-color:var(--acc);box-shadow:0 0 0 3px var(--accbg)}\n" as *u8) 425 o = of_cat(out, o, ".thm{display:none;margin-left:auto;background:transparent;color:var(--muted);border:1px solid var(--line);border-radius:16px;padding:5px 12px;font-size:.8rem;cursor:pointer;transition:color .15s,border-color .15s}.js .thm{display:block}.thm:hover{color:var(--acc);border-color:var(--acc)}\n" as *u8) 426 o = of_cat(out, o, ".wrap{max-width:1200px;margin:0 auto;padding:16px 20px 44px}\n" as *u8) 427 o = of_cat(out, o, ".card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px 18px;margin:14px 0}\n" as *u8) 428 o = of_cat(out, o, "table{border-collapse:collapse;width:100%}th,td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--line);font-size:.95rem}thead th{color:var(--muted);font-weight:600;font-size:.85rem}\n" as *u8) 429 o = of_cat(out, o, ".k{display:inline-block;padding:1px 10px;border-radius:20px;font-size:.8rem;font-weight:600;color:rgb(255,255,255)}.k0{background:rgb(41,84,164)}.k1{background:rgb(26,127,55)}.k2{background:rgb(178,106,0)}\n" as *u8) 430 o = of_cat(out, o, "textarea{width:100%;min-height:220px;font-family:ui-monospace,Consolas,monospace;font-size:.92rem;border:1px solid var(--line);border-radius:8px;padding:10px;background:var(--soft);color:var(--fg)}\n" as *u8) 431 o = of_cat(out, o, "input[type=text]{border:1px solid var(--line);border-radius:8px;padding:7px 10px;font-size:.95rem;background:var(--soft);color:var(--fg)}\n" as *u8) 432 o = of_cat(out, o, "button{background:var(--acc);color:var(--accfg);border:0;border-radius:8px;padding:9px 18px;font-size:.95rem;font-weight:600;cursor:pointer;transition:filter .15s,transform .1s}button:hover{filter:brightness(1.08)}button:active{transform:scale(.97)}button.ghost{background:var(--soft);color:var(--acc);border:1px solid var(--line);padding:4px 12px;font-size:.82rem}button.ghost:hover{filter:none;border-color:var(--acc)}\n" as *u8) 433 o = of_cat(out, o, ".hint{color:var(--muted);font-size:.85rem;margin-top:6px}.foot{max-width:1200px;margin:26px auto 0;padding:10px 20px 20px;color:var(--muted);font-size:.8rem;border-top:1px solid var(--line)}\n" as *u8) 434 // ---- home: create tiles, files header (chips + sort), card grid with REAL thumbnails, empty states 435 o = of_cat(out, o, ".newrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin:10px 0 4px}\n" as *u8) 436 o = of_cat(out, o, ".newt{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:12px 14px;transition:box-shadow .18s,border-color .18s}.newt:hover{border-color:var(--acc);box-shadow:0 4px 14px var(--sh)}.newt h3{margin:0 0 8px;font-size:.95rem;display:flex;align-items:center;gap:8px}.newt p{margin:8px 0 0}.newt p.row{display:flex;gap:8px}.newt input[type=text]{flex:1;min-width:0}.newt button{padding:7px 14px;font-size:.88rem}\n" as *u8) 437 o = of_cat(out, o, ".fico{width:26px;height:26px;min-width:26px;border-radius:7px;color:rgb(255,255,255);font-weight:700;font-size:.7rem;display:flex;align-items:center;justify-content:center}\n" as *u8) 438 o = of_cat(out, o, ".fhead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:20px 0 2px}.fhead h1{margin:0;font-size:clamp(17px,2vw,21px)}.cnt{color:var(--muted);font-size:.85rem;font-weight:400}\n" as *u8) 439 o = of_cat(out, o, ".chips{display:flex;gap:6px;flex-wrap:wrap}.chips a{text-decoration:none;font-size:.82rem;font-weight:600;padding:4px 14px;min-height:44px;display:inline-flex;align-items:center;border-radius:22px;border:1px solid var(--line);color:var(--muted);transition:color .15s,border-color .15s,background .15s}.chips a:hover{color:var(--acc);border-color:var(--acc)}.chips a.on{background:var(--accbg);color:var(--acc);border-color:var(--acc)}\n" as *u8) 440 o = of_cat(out, o, ".sortl{margin-left:auto;display:flex;align-items:center;font-size:.82rem;color:var(--muted)}.sortl a{text-decoration:none;margin-left:4px;color:var(--muted);min-height:44px;display:inline-flex;align-items:center;padding:0 6px}.sortl a.on{font-weight:700;color:var(--acc)}\n" as *u8) 441 o = of_cat(out, o, ".fgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(225px,1fr));gap:14px;margin-top:12px}\n" as *u8) 442 o = of_cat(out, o, ".fcard{display:block;background:var(--card);border:1px solid var(--line);border-radius:12px;overflow:hidden;text-decoration:none;color:var(--fg);transition:box-shadow .18s,transform .18s,border-color .18s}.fcard:hover{transform:translateY(-2px);border-color:var(--acc);box-shadow:0 8px 22px var(--sh2)}\n" as *u8) 443 o = of_cat(out, o, ".thumb{height:128px;overflow:hidden;background:var(--soft);border-bottom:1px solid var(--line);padding:10px 12px;pointer-events:none}\n" as *u8) 444 o = of_cat(out, o, ".tdoc{font-size:.55rem;line-height:1.5;color:var(--fg)}.tdoc .th{font-weight:700;font-size:.72rem;margin:0 0 2px}.tdoc .tb{font-weight:700}.tdoc .ti{font-style:italic}\n" as *u8) 445 o = of_cat(out, o, "table.tsheet{border-collapse:collapse;font-size:.55rem;width:auto}table.tsheet td{border:1px solid var(--line);padding:2px 6px;max-width:64px;overflow:hidden;white-space:nowrap}table.tsheet tr:first-child td{background:var(--accbg);font-weight:700}\n" as *u8) 446 o = of_cat(out, o, ".tslide{border:1px solid var(--line);border-radius:6px;background:var(--card);padding:8px 10px;box-shadow:0 2px 6px var(--sh)}.tslide .tst{font-weight:700;font-size:.66rem;margin-bottom:3px}.tslide .tsb{font-size:.55rem;color:var(--muted)}\n" as *u8) 447 o = of_cat(out, o, ".fmeta{display:flex;align-items:center;gap:9px;padding:10px 12px}.fmeta .nm{min-width:0}.fmeta .nm b{display:block;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fmeta .nm span{font-size:.76rem;color:var(--muted)}\n" as *u8) 448 o = of_cat(out, o, ".empty{text-align:center;padding:44px 20px;color:var(--muted)}.empty .row{display:flex;gap:10px;justify-content:center;margin-bottom:14px}.empty .fico{width:38px;height:38px;font-size:.95rem;border-radius:10px}.empty h2{margin:0 0 4px;color:var(--fg)}.empty p{margin:0}\n" as *u8) 449 // ---- editor page: crumb, saved stamp, find highlights 450 o = of_cat(out, o, ".stamp{display:inline-block;margin-left:10px;font-size:.78rem;font-weight:600;color:var(--good);background:var(--accbg);border-radius:12px;padding:2px 10px;vertical-align:middle}\n" as *u8) 451 o = of_cat(out, o, "mark.fm{background:var(--mark);color:inherit;border-radius:2px;padding:0 1px}mark.fm.cur{outline:2px solid var(--acc)}\n" as *u8) 452 // ---- visual editor (WYSIWYG surfaces; hidden until app.js flips html.js -> progressive enhancement) 453 o = of_cat(out, o, ".starter{display:none}.toolbar{display:none;flex-wrap:wrap;gap:6px;margin:0 0 10px;align-items:center}.js .toolbar{display:flex}\n" as *u8) 454 o = of_cat(out, o, ".toolbar button{background:var(--accbg);color:var(--acc);padding:5px 11px;font-size:.85rem;font-weight:600}.findw{display:flex;gap:6px;margin-left:auto;align-items:center}.findw input{padding:5px 10px;font-size:.85rem;border-radius:16px;max-width:150px}\n" as *u8) 455 o = of_cat(out, o, ".visual{display:none}.js .visual{display:block}[contenteditable]{outline:0}[contenteditable]:focus-within,[contenteditable]:focus{box-shadow:0 0 0 2px var(--accbg)}\n" as *u8) 456 o = of_cat(out, o, ".doc{border:1px solid var(--line);border-radius:8px;padding:14px 16px;min-height:220px;background:var(--soft)}.doc h2{font-size:1.2rem;margin:.4em 0 .2em}.doc p{margin:.35em 0}\n" as *u8) 457 o = of_cat(out, o, ".doc table.edt{border-collapse:collapse;margin:.5em 0}.doc table.edt td{border:1px solid var(--line);padding:4px 8px;min-width:60px}\n" as *u8) 458 o = of_cat(out, o, "table.sheet{border-collapse:collapse;width:100%}table.sheet td{border:1px solid var(--line);padding:5px 9px;min-width:70px}table.sheet tr:first-child td{background:var(--accbg);font-weight:600}\n" as *u8) 459 o = of_cat(out, o, ".deck{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px}.slide{border:1px solid var(--line);border-radius:8px;padding:12px;overflow:auto;background:var(--soft)}.slide h3{margin:0 0 6px;font-size:1rem}.slide ul{margin:0;padding-left:18px}.slide .tools{margin:8px 0 0}.slide .tools button{background:transparent;color:var(--muted);padding:2px 6px;font-size:.72rem;font-weight:500}\n" as *u8) 460 o = of_cat(out, o, ".rawwrap{margin:12px 0}.rawwrap summary{cursor:pointer;color:var(--muted);font-size:.85rem}button.save{margin-top:4px}\n" as *u8) 461 // wide tables never sideways-scroll the page on a phone -- they scroll inside their own wrapper 462 o = of_cat(out, o, ".tablewrap{overflow-x:auto} 463/* U4 loading skeletons: a shimmer placeholder honestly says work-in-progress, where a blank pane reads as broken. 464 Held to prefers-reduced-motion like every other animation here. */ 465.skel{background:linear-gradient(90deg,var(--soft) 25%,var(--line) 37%,var(--soft) 63%);background-size:400% 100%;animation:shim 1.4s ease infinite;border-radius:6px;color:transparent!important} 466.skel *{visibility:hidden} 467@keyframes shim{0%{background-position:100% 50%}100%{background-position:0 50%}} 468@media(prefers-reduced-motion:reduce){.skel{animation:none}} 469.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n" as *u8) 470 // ---- version diff (sibling lane; rgba overlays read on BOTH themes so no dark block needed) 471 o = of_cat(out, o, ".crumb{font-size:.85rem;margin:2px 0 12px}.crumb a{text-decoration:none}.diff{font-family:ui-monospace,Consolas,monospace;font-size:.85rem;border:1px solid var(--line);border-radius:8px;overflow:auto}.diff>div{padding:2px 10px;white-space:pre-wrap;border-bottom:1px solid var(--line)}.dadd{background:rgba(46,160,84,0.15);color:var(--good)}.ddel{background:rgba(205,70,70,0.13);color:rgb(190,85,85)}.dkeep{color:var(--muted)}\n" as *u8) 472 // ---- responsive: the shell collapses gracefully on phones 473 o = of_cat(out, o, "@media(max-width:640px){.top{padding:8px 12px;gap:8px}a.bname span+span{display:none}.wrap{padding:12px 12px 34px}.fgrid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}.thumb{height:96px}.sortl{margin-left:0}}\n" as *u8) 474 o = of_cat(out, o, "</style>" as *u8) 475 return o 476} 477// escape src[a,b) (XML & < >) while appending -> for emitting substrings without a NUL terminator 478func of_esc_n(out: *u8, off: i64, src: *u8, a: i64, b: i64) -> i64 { 479 var o: i64 = off 480 var i: i64 = a 481 while i < b { 482 let c: i64 = src[i] as i64 483 if c == 38 { o = of_cat(out, o, "&amp;" as *u8) } else { 484 if c == 60 { o = of_cat(out, o, "&lt;" as *u8) } else { 485 if c == 62 { o = of_cat(out, o, "&gt;" as *u8) } else { out[o] = src[i]; o = o + 1 } } } 486 i = i + 1 487 } 488 return o 489} 490// render a doc spec (H/B/I/P/T lines) as an editable block tree (#ed). Consecutive T lines = one table. 491func of_render_doc(out: *u8, off: i64, spec: *u8, sl: i64) -> i64 { 492 var o: i64 = of_cat(out, off, "<div id='ed' class='visual doc' contenteditable='true'>" as *u8) 493 var i: i64 = 0 494 var intable: i64 = 0 495 while i < sl { 496 var e: i64 = i 497 while e < sl { if spec[e] == (10 as u8) { break } e = e + 1 } 498 let c0: i64 = spec[i] as i64 499 var cs: i64 = i 500 if e >= i + 2 { if spec[i+1] == (32 as u8) { cs = i + 2 } } 501 if c0 == 84 { // 'T' table row 502 if intable == 0 { o = of_cat(out, o, "<table class='edt'><tbody>" as *u8); intable = 1 } 503 o = of_cat(out, o, "<tr>" as *u8) 504 var cstart: i64 = cs 505 var k: i64 = cs 506 while k <= e { 507 if k == e { o = of_cat(out, o, "<td>" as *u8); o = of_esc_n(out, o, spec, cstart, k); o = of_cat(out, o, "</td>" as *u8); k = k + 1 } 508 else { if spec[k] == (124 as u8) { o = of_cat(out, o, "<td>" as *u8); o = of_esc_n(out, o, spec, cstart, k); o = of_cat(out, o, "</td>" as *u8); cstart = k + 1; k = k + 1 } else { k = k + 1 } } 509 } 510 o = of_cat(out, o, "</tr>" as *u8) 511 } else { 512 if intable == 1 { o = of_cat(out, o, "</tbody></table>" as *u8); intable = 0 } 513 if c0 == 72 { o = of_cat(out, o, "<h2>" as *u8); o = of_esc_n(out, o, spec, cs, e); o = of_cat(out, o, "</h2>" as *u8) } 514 else { if c0 == 66 { o = of_cat(out, o, "<p data-k='B'><b>" as *u8); o = of_esc_n(out, o, spec, cs, e); o = of_cat(out, o, "</b></p>" as *u8) } 515 else { if c0 == 73 { o = of_cat(out, o, "<p data-k='I'><i>" as *u8); o = of_esc_n(out, o, spec, cs, e); o = of_cat(out, o, "</i></p>" as *u8) } 516 else { o = of_cat(out, o, "<p>" as *u8); o = of_esc_n(out, o, spec, cs, e); o = of_cat(out, o, "</p>" as *u8) } } } 517 } 518 i = e + 1 519 } 520 if intable == 1 { o = of_cat(out, o, "</tbody></table>" as *u8) } 521 o = of_cat(out, o, "</div>" as *u8) 522 return o 523} 524// render a sheet spec (TSV) as an editable grid (#grid). 525func of_render_sheet(out: *u8, off: i64, spec: *u8, sl: i64) -> i64 { 526 var o: i64 = of_cat(out, off, "<table id='grid' class='visual sheet'><tbody>" as *u8) 527 var i: i64 = 0 528 while i < sl { 529 var e: i64 = i 530 while e < sl { if spec[e] == (10 as u8) { break } e = e + 1 } 531 o = of_cat(out, o, "<tr>" as *u8) 532 var cstart: i64 = i 533 var k: i64 = i 534 while k <= e { 535 if k == e { o = of_cat(out, o, "<td contenteditable='true'>" as *u8); o = of_esc_n(out, o, spec, cstart, k); o = of_cat(out, o, "</td>" as *u8); k = k + 1 } 536 else { if spec[k] == (9 as u8) { o = of_cat(out, o, "<td contenteditable='true'>" as *u8); o = of_esc_n(out, o, spec, cstart, k); o = of_cat(out, o, "</td>" as *u8); cstart = k + 1; k = k + 1 } else { k = k + 1 } } 537 } 538 o = of_cat(out, o, "</tr>" as *u8) 539 i = e + 1 540 } 541 o = of_cat(out, o, "</tbody></table>" as *u8) 542 return o 543} 544// render a deck spec (S title / B bullet) as editable slide cards (#deck). 545func of_render_deck(out: *u8, off: i64, spec: *u8, sl: i64) -> i64 { 546 var o: i64 = of_cat(out, off, "<div id='deck' class='visual deck'>" as *u8) 547 var i: i64 = 0 548 var inslide: i64 = 0 549 while i < sl { 550 var e: i64 = i 551 while e < sl { if spec[e] == (10 as u8) { break } e = e + 1 } 552 let c0: i64 = spec[i] as i64 553 var cs: i64 = i 554 if e >= i + 2 { if spec[i+1] == (32 as u8) { cs = i + 2 } } 555 if c0 == 83 { // 'S' new slide 556 if inslide == 1 { o = of_cat(out, o, "</ul><p class='tools'><button type='button' data-act='bullet'>+ bullet</button> <button type='button' data-act='delslide'>remove slide</button></p></div>" as *u8) } 557 o = of_cat(out, o, "<div class='slide'><h3 contenteditable='true'>" as *u8); o = of_esc_n(out, o, spec, cs, e); o = of_cat(out, o, "</h3><ul>" as *u8) 558 inslide = 1 559 } else { if c0 == 66 { // 'B' bullet 560 if inslide == 0 { o = of_cat(out, o, "<div class='slide'><h3 contenteditable='true'>Slide</h3><ul>" as *u8); inslide = 1 } 561 o = of_cat(out, o, "<li contenteditable='true'>" as *u8); o = of_esc_n(out, o, spec, cs, e); o = of_cat(out, o, "</li>" as *u8) 562 } } 563 i = e + 1 564 } 565 if inslide == 1 { o = of_cat(out, o, "</ul><p class='tools'><button type='button' data-act='bullet'>+ bullet</button> <button type='button' data-act='delslide'>remove slide</button></p></div>" as *u8) } 566 o = of_cat(out, o, "</div>" as *u8) 567 return o 568} 569// kind-specific editing toolbar (buttons carry data-act -> app.js) + shared undo/redo/find controls. 570func of_toolbar(out: *u8, off: i64, ks: i64) -> i64 { 571 var o: i64 = of_cat(out, off, "<div class='toolbar'>" as *u8) 572 if ks == 0 { o = of_cat(out, o, "<button type='button' data-act='h'>Heading</button><button type='button' data-act='b'>Bold line</button><button type='button' data-act='i'>Italic line</button><button type='button' data-act='p'>Plain</button><button type='button' data-act='table'>+ table</button><button type='button' data-act='trow'>+ row</button>" as *u8) } 573 if ks == 1 { o = of_cat(out, o, "<button type='button' data-act='row'>+ row</button><button type='button' data-act='col'>+ column</button>" as *u8) } 574 if ks == 2 { o = of_cat(out, o, "<button type='button' data-act='slide'>+ slide</button>" as *u8) } 575 o = of_cat(out, o, "<button type='button' data-act='u' title='Undo (Ctrl+Z)'>Undo</button><button type='button' data-act='r' title='Redo (Ctrl+Y)'>Redo</button><span class='findw'><input id='findq' type='text' placeholder='Find in file'><button type='button' data-act='find'>Find</button></span>" as *u8) 576 o = of_cat(out, o, "</div>" as *u8) 577 return o 578} 579// serve the client at /app.js (read from CWD; NishiLang literal traps -> JS MUST live in a file, never inlined). 580// Static client assets (office_app.js, office_sw.js) live beside the SERVICE root, but a gate runs 581// from buildroot/. A bare cwd-relative read therefore resolves for the daemon and 404s for the gate, 582// which is how five teeth (T3c, T12i, T13d, T-U4-b, T-U4-c) failed while the server itself was fine. 583// Resolve through an ORDERED ROOT LIST so the answer does not depend on where the process happened 584// to be launched -- the build-cwd-is-not-run-cwd law, and rule 17's configuration hierarchy applied 585// to a file path. A symlink would have hidden this; it is the consumer that has to resolve. 586// Returns bytes read, or <=0 if no root has the asset. Frees what it takes. 587func of_read_asset(name: *u8, buf: *u8, cap: i64) -> i64 { 588 var n: i64 = of_read_file(name, buf, cap) 589 if n > 0 { return n } 590 let p: *u8 = sys_mmap(1024) 591 var o: i64 = of_cat(p, 0, "../" as *u8) 592 o = of_cat(p, o, name) 593 p[o] = 0 as u8 594 n = of_read_file(p, buf, cap) 595 sys_munmap(p, 1024) 596 return n 597} 598 599func of_serve_js(out: *u8, cap: i64) -> i64 { 600 let fb: *u8 = sys_mmap(131072) 601 let fl: i64 = of_read_asset("office_app.js" as *u8, fb, 131071) 602 if fl <= 0 { return of_err(out, "404 Not Found" as *u8, "app.js missing" as *u8) } 603 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: application/javascript; charset=utf-8\r\nContent-Length: " as *u8) 604 o = of_catn(out, o, fl) 605 o = of_cat(out, o, "\r\nCache-Control: max-age=300\r\n\r\n" as *u8) 606 var i: i64 = 0 607 while i < fl { if o + i < cap { out[o + i] = fb[i] } i = i + 1 } 608 return o + fl 609} 610// U4 OFFLINE/PWA. The service worker lives in a FILE for the same reason app.js does -- NishiLang literal 611// traps make inlining JS a hazard. It is served at /sw.js so its scope covers the whole office mount; a worker 612// served from a deeper path could not control the app it is meant to make offline-capable. 613func of_serve_sw(out: *u8, cap: i64) -> i64 { 614 let fb: *u8 = sys_mmap(65536) 615 let fl: i64 = of_read_asset("office_sw.js" as *u8, fb, 65535) 616 if fl <= 0 { return of_err(out, "404 Not Found" as *u8, "sw.js missing" as *u8) } 617 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK 618 619Content-Type: application/javascript; charset=utf-8 620 621Service-Worker-Allowed: / 622 623Content-Length: " as *u8) 624 o = of_catn(out, o, fl) 625 o = of_cat(out, o, " 626 627Cache-Control: max-age=60 628 629 630 631" as *u8) 632 var i: i64 = 0 633 while i < fl { if o + i < cap { out[o + i] = fb[i] } i = i + 1 } 634 return o + fl 635} 636// Web app manifest -- installable to a home screen, which is what "offline" means to a family on a phone. 637func of_serve_manifest(out: *u8, base: *u8, cap: i64) -> i64 { 638 let b: *u8 = sys_mmap(4096) 639 var m: i64 = of_cat(b, 0, "{\"name\":\"Nishi Office\",\"short_name\":\"Office\",\"display\":\"standalone\",\"background_color\":\"rgb(244,246,251)\",\"theme_color\":\"rgb(41,84,164)\",\"start_url\":\"" as *u8) 640 m = of_cat(b, m, base) 641 m = of_cat(b, m, "/\"}" as *u8) 642 b[m] = 0 as u8 643 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK 644 645Content-Type: application/manifest+json 646 647Content-Length: " as *u8) 648 o = of_catn(out, o, m) 649 o = of_cat(out, o, " 650 651 652 653" as *u8) 654 o = of_cat(out, o, b) 655 return o 656} 657func of_page_top(out: *u8, off: i64, title: *u8) -> i64 { 658 var o: i64 = off 659 o = of_cat(out, o, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<" as *u8) 660 o = of_catc(out, o, 33) 661 o = of_cat(out, o, "DOCTYPE html>\n<html lang=" as *u8) 662 o = of_catc(out, o, 34) 663 o = of_cat(out, o, "en" as *u8) 664 o = of_catc(out, o, 34) 665 o = of_cat(out, o, "><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>" as *u8) 666 o = of_esc(out, o, title) 667 // favicon: inline SVG data URI, percent-encoded (no raw hash/bang -- nx_cc literal law) 668 o = of_cat(out, o, "</title><link rel='icon' href='data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 32 32%22%3E%3Crect width=%2232%22 height=%2232%22 rx=%227%22 fill=%22rgb(41,84,164)%22/%3E%3Ctext x=%2216%22 y=%2223%22 font-size=%2218%22 font-weight=%22bold%22 font-family=%22sans-serif%22 fill=%22white%22 text-anchor=%22middle%22%3EN%3C/text%3E%3C/svg%3E'>" as *u8) 669 o = of_css(out, o) 670 o = of_cat(out, o, "</head><body>\n" as *u8) 671 return o 672} 673func of_page_foot(out: *u8, off: i64) -> i64 { 674 var o: i64 = off 675 o = of_cat(out, o, "<p class='foot'>Nishi Office &mdash; sovereign engines nx_docx &middot; nx_xlsx &middot; nx_pptx (gated); every save is a NEW version, history is never lost. Search, thumbnails, diffs and raw-spec editing work with ZERO JS; visual editing, find, undo, shortcuts and autosave light up with it. Co-edit wiring and in-app AI are the named next rungs.</p></body></html>\n" as *u8) 676 return o 677} 678// the app shell: sticky top bar with brand, live search (GET <base>/?q=) and a JS-only theme toggle. 679// q = the current search text (prefilled so the state is visible); pass an empty buffer elsewhere. 680func of_shell_top(out: *u8, off: i64, title: *u8, base: *u8, q: *u8) -> i64 { 681 var o: i64 = of_page_top(out, off, title) 682 // U4 PWA: installable + a theme colour so the OS chrome matches the app instead of flashing white. 683 // Emitted HERE, not in of_page_top: only the APP SHELL is installable. The bare share/error pages have no 684 // base mount and are not an app -- advertising a manifest from them would install a broken scope. 685 o = of_cat(out, o, "<meta name='theme-color' content='rgb(41,84,164)'><link rel='manifest' href='" as *u8) 686 o = of_cat(out, o, base) 687 o = of_cat(out, o, "/manifest.webmanifest'>" as *u8) 688 // skip-to-content for keyboard/screen-reader users (href='#main'; hash composed via catc) 689 o = of_cat(out, o, "<a class='skip-link' href='" as *u8) 690 o = of_catc(out, o, 35) 691 o = of_cat(out, o, "main'>Skip to content</a><header class='top'><nav><a class='bname' href='" as *u8) 692 o = of_cat(out, o, base) 693 o = of_cat(out, o, "/'><svg class='logo' viewBox='0 0 32 32' aria-hidden='true'><rect width='32' height='32' rx='7' fill='rgb(41,84,164)'/><text x='16' y='23' font-size='18' font-weight='bold' fill='white' text-anchor='middle'>N</text></svg><span>Nishi Office</span></a><form method='get' action='" as *u8) 694 o = of_cat(out, o, base) 695 o = of_cat(out, o, "/'><input type='text' name='q' placeholder='Search files' value='" as *u8) 696 o = of_esc(out, o, q) 697 o = of_cat(out, o, "'></form><button type='button' class='thm' data-act='theme'>Theme</button></nav></header>\n" as *u8) 698 return o 699} 700// human "edited ago" from a usec timestamp (0 = unknown) 701func of_ago(out: *u8, off: i64, us: i64) -> i64 { 702 if us <= 0 { return of_cat(out, off, "&mdash;" as *u8) } 703 var d: i64 = (sys_now_us() - us) / 1000000 704 if d < 0 { d = 0 } 705 if d < 90 { return of_cat(out, off, "just now" as *u8) } 706 if d < 5400 { var o: i64 = of_catn(out, off, d / 60); return of_cat(out, o, "m ago" as *u8) } 707 if d < 129600 { var o2: i64 = of_catn(out, off, d / 3600); return of_cat(out, o2, "h ago" as *u8) } 708 var o3: i64 = of_catn(out, off, d / 86400) 709 return of_cat(out, o3, "d ago" as *u8) 710} 711// usec of the LATEST save = field 3 of the last non-empty manifest line (0 if missing) -> recency sort + stamps 712func of_manifest_last_us(root: *u8, name: *u8) -> i64 { 713 let mp: *u8 = sys_mmap(512) 714 var o: i64 = of_cat(mp, 0, root); o = of_cat(mp, o, "/" as *u8); o = of_cat(mp, o, name); o = of_cat(mp, o, "/manifest.txt" as *u8); mp[o] = 0 as u8 715 let buf: *u8 = sys_mmap(65536) 716 let n: i64 = of_read_file(mp, buf, 65536) 717 if n <= 0 { return 0 } 718 var e: i64 = n 719 while e > 0 { if buf[e-1] == (10 as u8) { e = e - 1 } else { break } } 720 if e <= 0 { return 0 } 721 var s: i64 = e 722 while s > 0 { if buf[s-1] == (10 as u8) { break } s = s - 1 } 723 var tabs: i64 = 0 724 var i: i64 = s 725 while i < e { if buf[i] == (9 as u8) { tabs = tabs + 1; i = i + 1; if tabs == 2 { break } } else { i = i + 1 } } 726 if tabs < 2 { return 0 } 727 var v: i64 = 0 728 while i < e { let c: i64 = buf[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } 729 return v 730} 731// 1 if the manifest line for v<N> carries the additive 4th field "auto" (a background autosave), else 0 732func of_manifest_is_auto(root: *u8, name: *u8, vn: i64) -> i64 { 733 let mp: *u8 = sys_mmap(512) 734 var o: i64 = of_cat(mp, 0, root); o = of_cat(mp, o, "/" as *u8); o = of_cat(mp, o, name); o = of_cat(mp, o, "/manifest.txt" as *u8); mp[o] = 0 as u8 735 let buf: *u8 = sys_mmap(65536) 736 let n: i64 = of_read_file(mp, buf, 65536) 737 if n <= 0 { return 0 } 738 let pfx: *u8 = sys_mmap(32) 739 var po: i64 = of_cat(pfx, 0, "v" as *u8); po = of_catn(pfx, po, vn); po = of_catc(pfx, po, 9); pfx[po] = 0 as u8 740 var i: i64 = 0 741 while i < n { 742 var m: i64 = 1 743 var k: i64 = 0 744 while pfx[k] != (0 as u8) { 745 if i + k >= n { m = 0; break } 746 if buf[i+k] != pfx[k] { m = 0; break } 747 k = k + 1 748 } 749 var e: i64 = i 750 while e < n { if buf[e] == (10 as u8) { break } e = e + 1 } 751 if m == 1 { 752 var tabs: i64 = 0 753 var j: i64 = i 754 while j < e { 755 if buf[j] == (9 as u8) { 756 tabs = tabs + 1 757 if tabs == 3 { 758 if j + 4 < e { if buf[j+1] == (97 as u8) { if buf[j+2] == (117 as u8) { if buf[j+3] == (116 as u8) { if buf[j+4] == (111 as u8) { return 1 } } } } } 759 return 0 760 } 761 } 762 j = j + 1 763 } 764 return 0 765 } 766 i = e + 1 767 } 768 return 0 769} 770// server-rendered mini preview of the LATEST spec -> the home card thumbnail (real content, zero JS) 771func of_thumb(out: *u8, off: i64, root: *u8, name: *u8, ks: i64, vc: i64) -> i64 { 772 var o: i64 = of_cat(out, off, "<div class='thumb'>" as *u8) 773 let vd: *u8 = sys_mmap(512) 774 of_vdir(root, name, vc, vd) 775 let sp: *u8 = sys_mmap(600) 776 var so: i64 = of_cat(sp, 0, vd); so = of_cat(sp, so, "/spec.txt" as *u8); sp[so] = 0 as u8 777 let buf: *u8 = sys_mmap(600) 778 let sl: i64 = of_read_file(sp, buf, 520) 779 if sl <= 0 { return of_cat(out, o, "<div class='tdoc'>&hellip;</div></div>" as *u8) } 780 if ks == 0 { 781 o = of_cat(out, o, "<div class='tdoc'>" as *u8) 782 var i: i64 = 0 783 var lines: i64 = 0 784 while i < sl { 785 if lines >= 7 { break } 786 var e: i64 = i 787 while e < sl { if buf[e] == (10 as u8) { break } e = e + 1 } 788 let c0: i64 = buf[i] as i64 789 var cs: i64 = i 790 if e >= i + 2 { if buf[i+1] == (32 as u8) { cs = i + 2 } } 791 var ce: i64 = e 792 if ce > cs + 64 { ce = cs + 64 } 793 if c0 == 72 { o = of_cat(out, o, "<div class='th'>" as *u8) } else { 794 if c0 == 66 { o = of_cat(out, o, "<div class='tb'>" as *u8) } else { 795 if c0 == 73 { o = of_cat(out, o, "<div class='ti'>" as *u8) } else { o = of_cat(out, o, "<div>" as *u8) } } } 796 o = of_esc_n(out, o, buf, cs, ce) 797 o = of_cat(out, o, "</div>" as *u8) 798 lines = lines + 1 799 i = e + 1 800 } 801 o = of_cat(out, o, "</div>" as *u8) 802 } 803 if ks == 1 { 804 o = of_cat(out, o, "<table class='tsheet'><tbody>" as *u8) 805 var i2: i64 = 0 806 var rows: i64 = 0 807 while i2 < sl { 808 if rows >= 5 { break } 809 var e2: i64 = i2 810 while e2 < sl { if buf[e2] == (10 as u8) { break } e2 = e2 + 1 } 811 o = of_cat(out, o, "<tr>" as *u8) 812 var cstart: i64 = i2 813 var k: i64 = i2 814 var cells: i64 = 0 815 while k <= e2 { 816 if cells >= 4 { break } 817 var hit: i64 = 0 818 if k == e2 { hit = 1 } else { if buf[k] == (9 as u8) { hit = 1 } } 819 if hit == 1 { 820 var ce2: i64 = k 821 if ce2 > cstart + 14 { ce2 = cstart + 14 } 822 o = of_cat(out, o, "<td>" as *u8); o = of_esc_n(out, o, buf, cstart, ce2); o = of_cat(out, o, "</td>" as *u8) 823 cstart = k + 1 824 cells = cells + 1 825 } 826 k = k + 1 827 } 828 o = of_cat(out, o, "</tr>" as *u8) 829 rows = rows + 1 830 i2 = e2 + 1 831 } 832 o = of_cat(out, o, "</tbody></table>" as *u8) 833 } 834 if ks == 2 { 835 o = of_cat(out, o, "<div class='tslide'>" as *u8) 836 var i3: i64 = 0 837 var started: i64 = 0 838 var bl: i64 = 0 839 while i3 < sl { 840 var e3: i64 = i3 841 while e3 < sl { if buf[e3] == (10 as u8) { break } e3 = e3 + 1 } 842 let c3: i64 = buf[i3] as i64 843 var cs3: i64 = i3 844 if e3 >= i3 + 2 { if buf[i3+1] == (32 as u8) { cs3 = i3 + 2 } } 845 var ce3: i64 = e3 846 if ce3 > cs3 + 56 { ce3 = cs3 + 56 } 847 if c3 == 83 { 848 if started == 1 { break } 849 o = of_cat(out, o, "<div class='tst'>" as *u8); o = of_esc_n(out, o, buf, cs3, ce3); o = of_cat(out, o, "</div>" as *u8) 850 started = 1 851 } else { if c3 == 66 { if bl < 3 { 852 o = of_cat(out, o, "<div class='tsb'>&bull; " as *u8); o = of_esc_n(out, o, buf, cs3, ce3); o = of_cat(out, o, "</div>" as *u8) 853 bl = bl + 1 854 } } } 855 i3 = e3 + 1 856 } 857 o = of_cat(out, o, "</div>" as *u8) 858 } 859 o = of_cat(out, o, "</div>" as *u8) 860 return o 861} 862// lowercase in place (search is case-insensitive; stored names are already lowercase by of_name_ok) 863func of_lower(s: *u8) -> i64 { 864 var i: i64 = 0 865 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 65 { if c <= 90 { s[i] = (c + 32) as u8 } } i = i + 1 } 866 return 0 867} 868// one filter/sort pill: preserves q, sets type (tv, empty = All) and sort (sv) explicitly 869func of_chip(out: *u8, off: i64, base: *u8, q: *u8, tv: *u8, sv: *u8, label: *u8, on: i64) -> i64 { 870 var o: i64 = of_cat(out, off, "<a class='" as *u8) 871 if on == 1 { o = of_cat(out, o, "on" as *u8) } 872 o = of_cat(out, o, "' href='" as *u8) 873 o = of_cat(out, o, base) 874 o = of_cat(out, o, "/?" as *u8) 875 if q[0] != (0 as u8) { o = of_cat(out, o, "q=" as *u8); o = of_esc(out, o, q); o = of_cat(out, o, "&amp;" as *u8) } 876 if tv[0] != (0 as u8) { o = of_cat(out, o, "type=" as *u8); o = of_cat(out, o, tv); o = of_cat(out, o, "&amp;" as *u8) } 877 o = of_cat(out, o, "sort=" as *u8) 878 o = of_cat(out, o, sv) 879 o = of_cat(out, o, "'>" as *u8) 880 o = of_cat(out, o, label) 881 o = of_cat(out, o, "</a>" as *u8) 882 return o 883} 884// first byte offset of needle in buf[0,n), or -1 -- lets the gate assert ORDERING, not just presence 885func of_findpos(buf: *u8, n: i64, needle: *u8) -> i64 { 886 let nl: i64 = of_slen(needle) 887 if nl == 0 { return 0 - 1 } 888 var i: i64 = 0 889 while i + nl <= n { 890 var k: i64 = 0 891 var hit: i64 = 1 892 while k < nl { if buf[i+k] != needle[k] { hit = 0; k = nl } else { k = k + 1 } } 893 if hit == 1 { return i } 894 i = i + 1 895 } 896 return 0 - 1 897} 898// one Start-new tile: pick a name, Create -> lands on the visual editor. The starter spec rides a HIDDEN INPUT 899// (a hidden default value is what type=hidden is FOR -- and unlike a display:none <textarea> it renders NOTHING 900// in every engine incl. Nishi Browser, so the tile shows no leaked spec text; newlines/tabs survive the POST via 901// URL-encoding, which of_form_get decodes). Submitted as-is, works with NO JS; the editor is where you compose. 902// ---- U3 LIBRARY ORGANISATION: starred + folders ------------------------------------------------------ 903// Both are SIDECAR files next to the manifest, exactly like agent.txt: the document spec stays pure content, 904// nothing about the file format changes, and a missing sidecar simply means "not starred / no folder". No 905// migration, no schema version, and an older daemon reading a newer tree just ignores them. 906func of_side_path(root: *u8, name: *u8, leaf: *u8, out: *u8) -> i64 { 907 var o: i64 = of_cat(out, 0, root); o = of_cat(out, o, "/" as *u8); o = of_cat(out, o, name) 908 o = of_cat(out, o, "/" as *u8); o = of_cat(out, o, leaf); out[o] = 0 as u8 909 return o 910} 911func of_starred(root: *u8, name: *u8) -> i64 { 912 let p: *u8 = sys_mmap(512) 913 of_side_path(root, name, "starred" as *u8, p) 914 let b: *u8 = sys_mmap(8) 915 if of_read_file(p, b, 4) > 0 { return 1 } 916 return 0 917} 918// toggle and return the NEW state. Unstar writes "0" rather than deleting: a retired star is still history, 919// and a write we can read back beats a delete we cannot audit. 920// Toggle and return the NEW state. Unstar writes a zeroed byte rather than deleting: a retired star is still 921// history, and a write we can read back beats a delete we cannot audit. 922// NOTE: never pass the "" literal here -- the nx_cc constant pool ALIASES an empty literal onto the NEXT 923// literal in the pool, so the "empty" write would emit someone else's bytes. Use a real zeroed buffer. 924func of_star_toggle(root: *u8, name: *u8) -> i64 { 925 let p: *u8 = sys_mmap(512) 926 of_side_path(root, name, "starred" as *u8, p) 927 if of_starred(root, name) == 1 { 928 let z: *u8 = sys_mmap(8); z[0] = 0 as u8 929 of_write_file(p, z, 0) 930 return 0 931 } 932 of_write_file(p, "1" as *u8, 1) 933 return 1 934} 935func of_folder_get(root: *u8, name: *u8, out: *u8, cap: i64) -> i64 { 936 let p: *u8 = sys_mmap(512) 937 of_side_path(root, name, "folder" as *u8, p) 938 let n: i64 = of_read_file(p, out, cap - 1) 939 if n <= 0 { out[0] = 0 as u8; return 0 } 940 var e: i64 = n 941 var trim: i64 = 1 942 while trim == 1 { 943 if e <= 0 { trim = 0 } else { 944 let c: i64 = out[e-1] as i64 945 if c == 10 { e = e - 1 } else { if c == 13 { e = e - 1 } else { trim = 0 } } 946 } 947 } 948 out[e] = 0 as u8 949 return e 950} 951func of_folder_set(root: *u8, name: *u8, val: *u8) -> i64 { 952 let p: *u8 = sys_mmap(512) 953 of_side_path(root, name, "folder" as *u8, p) 954 return of_write_file(p, val, of_slen(val)) 955} 956// One template card. Same POST /save contract as of_form, so a template is not a special kind of file -- 957// it is an ordinary document that happens to start with useful content, and every downstream feature 958// (versioning, diff, AI, agent, sharing) works on it unchanged. 959func of_tmpl(out: *u8, off: i64, base: *u8, k: i64, icon: *u8, title: *u8, blurb: *u8, spec: *u8) -> i64 { 960 var o: i64 = of_cat(out, off, "<div class='newt'><h3><div class='fico k" as *u8) 961 o = of_catn(out, o, k) 962 o = of_cat(out, o, "'>" as *u8) 963 o = of_cat(out, o, icon) 964 o = of_cat(out, o, "</div>" as *u8) 965 o = of_cat(out, o, title) 966 o = of_cat(out, o, " <span class='cnt'>." as *u8); o = of_cat(out, o, of_ext(k)); o = of_cat(out, o, "</span></h3><form method='post' action='" as *u8) 967 o = of_cat(out, o, base) 968 o = of_cat(out, o, "/save'><input type='hidden' name='kind' value='" as *u8) 969 o = of_cat(out, o, of_kind_name(k)) 970 o = of_cat(out, o, "'><input type='hidden' name='spec' value='" as *u8) 971 o = of_esc(out, o, spec) 972 o = of_cat(out, o, "'><p class='hint' style='margin:0'>" as *u8) 973 o = of_cat(out, o, blurb) 974 o = of_cat(out, o, "</p><p class='row'><input type='text' name='name' placeholder='file-name (a-z 0-9 dash)' required><button type='submit'>Use</button></p></form></div>\n" as *u8) 975 return o 976} 977func of_form(out: *u8, off: i64, base: *u8, k: i64) -> i64 { 978 var o: i64 = off 979 o = of_cat(out, o, "<div class='newt'><h3><div class='fico k" as *u8) 980 o = of_catn(out, o, k) 981 o = of_cat(out, o, "'>" as *u8) 982 if k == 0 { o = of_cat(out, o, "W" as *u8) } 983 if k == 1 { o = of_cat(out, o, "S" as *u8) } 984 if k == 2 { o = of_cat(out, o, "P" as *u8) } 985 o = of_cat(out, o, "</div>New " as *u8) 986 o = of_cat(out, o, of_kind_name(k)) 987 o = of_cat(out, o, " <span class='cnt'>." as *u8); o = of_cat(out, o, of_ext(k)); o = of_cat(out, o, "</span></h3><form method='post' action='" as *u8) 988 o = of_cat(out, o, base) 989 o = of_cat(out, o, "/save'><input type='hidden' name='kind' value='" as *u8) 990 o = of_cat(out, o, of_kind_name(k)) 991 o = of_cat(out, o, "'><input type='hidden' name='spec' value='" as *u8) 992 if k == 0 { o = of_cat(out, o, "H Untitled document\nP Start writing here." as *u8) } 993 if k == 1 { o = of_cat(out, o, "Item\tAmount\nExample\t1" as *u8) } 994 if k == 2 { o = of_cat(out, o, "S Untitled deck\nB First point" as *u8) } 995 o = of_cat(out, o, "'>" as *u8) 996 if k == 0 { o = of_cat(out, o, "<p class='hint' style='margin:0'>Headings, bold, tables. Opens in Word.</p>" as *u8) } 997 if k == 1 { o = of_cat(out, o, "<p class='hint' style='margin:0'>Real formulas (=SUM, =AVERAGE&hellip;). Opens in Excel.</p>" as *u8) } 998 if k == 2 { o = of_cat(out, o, "<p class='hint' style='margin:0'>Titles and bullets. Opens in PowerPoint.</p>" as *u8) } 999 o = of_cat(out, o, "<p class='row'><input type='text' name='name' placeholder='file-name (a-z 0-9 dash)' required><button type='submit'>Create</button></p></form></div>\n" as *u8) 1000 return o 1001} 1002// the home APP SHELL (U-axes rung): search + type chips + recency/name sort + card grid with REAL content 1003// thumbnails + onboarding/no-match empty states. All server-rendered -- works with ZERO JS. 1004// qs = the raw query string (q=&type=&sort=), form-urlencoded exactly like a POST body. 1005func of_home(root: *u8, base: *u8, qs: *u8, out: *u8, cap: i64, azprefix: *u8, me: *u8, authed: i64) -> i64 { 1006 let ql: i64 = of_slen(qs) 1007 let q: *u8 = sys_mmap(96) 1008 let srt: *u8 = sys_mmap(24) 1009 let tf: *u8 = sys_mmap(24) 1010 of_form_get(qs, ql, "q" as *u8, q, 80) 1011 of_form_get(qs, ql, "sort" as *u8, srt, 24) 1012 of_form_get(qs, ql, "type" as *u8, tf, 24) 1013 let flt: *u8 = sys_mmap(24) 1014 let fld: *u8 = sys_mmap(64) 1015 of_form_get(qs, ql, "filter" as *u8, flt, 24) 1016 of_form_get(qs, ql, "folder" as *u8, fld, 48) 1017 // "shared with me" = docs the ReBAC reverse index grants me that I do NOT own. Answered from the existing 1018 // index rather than a second store, so sharing and the library view can never disagree. 1019 let shd: *i64 = sys_mmap(8 * 64) as *i64 1020 let own: *i64 = sys_mmap(8 * 64) as *i64 1021 var nshd: i64 = 0 1022 var nown: i64 = 0 1023 if of_seq(flt, "shared" as *u8) == 1 { if authed == 1 { 1024 nshd = of_my_docs(azprefix, me, shd, 64) 1025 nown = of_collect_docs(azprefix, me, "owner" as *u8, own, 0, 64) 1026 } } 1027 of_lower(q) 1028 var o: i64 = of_shell_top(out, 0, "Nishi Office" as *u8, base, q) 1029 o = of_cat(out, o, "<main id='main' class='wrap'>" as *u8) 1030 // collect entries from the append-only registry, filtered by type chip + search text 1031 let idx: *u8 = sys_mmap(512) 1032 var io: i64 = of_cat(idx, 0, root); io = of_cat(idx, io, "/index.txt" as *u8); idx[io] = 0 as u8 1033 let ib: *u8 = sys_mmap(65536) 1034 let n: i64 = of_read_file(idx, ib, 65536) 1035 let names: *u8 = sys_mmap(256 * 64) 1036 let kidx: *i64 = sys_mmap(256 * 8) as *i64 1037 let vcs: *i64 = sys_mmap(256 * 8) as *i64 1038 let uss: *i64 = sys_mmap(256 * 8) as *i64 1039 let ord: *i64 = sys_mmap(256 * 8) as *i64 1040 var total: i64 = 0 1041 var ne: i64 = 0 1042 let nm: *u8 = sys_mmap(64) 1043 let kd: *u8 = sys_mmap(32) 1044 let kb: *u8 = sys_mmap(64) 1045 var i: i64 = 0 1046 while i < n { 1047 var t: i64 = 0 1048 while i < n { if ib[i] == (9 as u8) { i = i + 1; break } if t < 63 { nm[t] = ib[i]; t = t + 1 } i = i + 1 } 1049 nm[t] = 0 as u8 1050 var t2: i64 = 0 1051 while i < n { if ib[i] == (10 as u8) { i = i + 1; break } if t2 < 31 { kd[t2] = ib[i]; t2 = t2 + 1 } i = i + 1 } 1052 kd[t2] = 0 as u8 1053 if t > 0 { 1054 total = total + 1 1055 var keep: i64 = 1 1056 if tf[0] != (0 as u8) { if of_seq(tf, kd) == 0 { keep = 0 } } 1057 if keep == 1 { if q[0] != (0 as u8) { if of_memhas(nm, of_slen(nm), q) == 0 { keep = 0 } } } 1058 if keep == 1 { if of_seq(flt, "starred" as *u8) == 1 { if of_starred(root, nm) == 0 { keep = 0 } } } 1059 if keep == 1 { if fld[0] != (0 as u8) { 1060 let fbuf: *u8 = sys_mmap(64) 1061 of_folder_get(root, nm, fbuf, 64) 1062 if of_seq(fbuf, fld) == 0 { keep = 0 } 1063 } } 1064 if keep == 1 { if of_seq(flt, "shared" as *u8) == 1 { 1065 var mine: i64 = 0 1066 var si: i64 = 0 1067 while si < nshd { if of_seq(shd[si] as *u8, nm) == 1 { mine = 1; si = nshd } else { si = si + 1 } } 1068 if mine == 0 { keep = 0 } 1069 if mine == 1 { 1070 var owned: i64 = 0 1071 var oi: i64 = 0 1072 while oi < nown { if of_seq(own[oi] as *u8, nm) == 1 { owned = 1; oi = nown } else { oi = oi + 1 } } 1073 if owned == 1 { keep = 0 } 1074 } 1075 } } 1076 if keep == 1 { if ne < 256 { 1077 let ki: i64 = of_kind_idx(kd) 1078 var ks: i64 = ki 1079 if ks < 0 { ks = 0 } 1080 var w: i64 = 0 1081 while nm[w] != (0 as u8) { names[ne * 64 + w] = nm[w]; w = w + 1 } 1082 names[ne * 64 + w] = 0 as u8 1083 kidx[ne] = ks 1084 vcs[ne] = of_manifest_count(root, nm, kb, 64) 1085 uss[ne] = of_manifest_last_us(root, nm) 1086 ord[ne] = ne 1087 ne = ne + 1 1088 } } 1089 } 1090 } 1091 // order: default = most recently edited first (Docs-style); sort=name = alphabetical 1092 var by_name: i64 = 0 1093 if of_seq(srt, "name" as *u8) == 1 { by_name = 1 } 1094 var a: i64 = 0 1095 while a < ne { 1096 var b: i64 = a + 1 1097 while b < ne { 1098 var sw: i64 = 0 1099 if by_name == 1 { 1100 let pa: *u8 = (names as i64 + ord[a] * 64) as *u8 1101 let pb: *u8 = (names as i64 + ord[b] * 64) as *u8 1102 var ci: i64 = 0 1103 var cmp: i64 = 0 1104 while cmp == 0 { 1105 let ca: i64 = pa[ci] as i64 1106 let cb: i64 = pb[ci] as i64 1107 if ca < cb { cmp = 0 - 1 } else { if ca > cb { cmp = 1 } else { if ca == 0 { cmp = 2 } else { ci = ci + 1 } } } 1108 } 1109 if cmp == 1 { sw = 1 } 1110 } else { 1111 if uss[ord[b]] > uss[ord[a]] { sw = 1 } 1112 } 1113 if sw == 1 { let tmp: i64 = ord[a]; ord[a] = ord[b]; ord[b] = tmp } 1114 b = b + 1 1115 } 1116 a = a + 1 1117 } 1118 // first-run onboarding: nothing exists yet 1119 if total == 0 { 1120 o = of_cat(out, o, "<div class='empty'><div class='row'><div class='fico k0'>W</div><div class='fico k1'>S</div><div class='fico k2'>P</div></div><h1>Create your first document</h1><p>Documents, spreadsheets and decks &mdash; created, versioned and downloadable, all on our own stack. Pick a name below to start.</p></div><div class='newrow'>" as *u8) 1121 o = of_form(out, o, base, 0) 1122 o = of_form(out, o, base, 1) 1123 o = of_form(out, o, base, 2) 1124 o = of_import_form(out, o, base) 1125 o = of_cat(out, o, "</div></main>" as *u8) 1126 o = of_page_foot(out, o) 1127 return o 1128 } 1129 o = of_cat(out, o, "<h2>Start new</h2><div class='newrow'>" as *u8) 1130 o = of_form(out, o, base, 0) 1131 o = of_form(out, o, base, 1) 1132 o = of_form(out, o, base, 2) 1133 o = of_import_form(out, o, base) 1134 o = of_cat(out, o, "</div>" as *u8) 1135 // ---- TEMPLATES GALLERY (U3): a blank page is the worst onboarding a suite can offer. Every template is a 1136 // REAL working spec -- the budget carries live =SUM and a #CF rule, the agenda a real table -- so opening one 1137 // demonstrates the engine instead of describing it. Zero JS: each card is a plain POST to the same /save. 1138 o = of_cat(out, o, "<h2>Templates</h2><p class='hint' style='margin:0 0 6px'>Start from something real rather than a blank page. Each one opens as a normal file you can edit, version and download.</p><div class='newrow'>" as *u8) 1139 o = of_tmpl(out, o, base, 0, "W", "Letter", "A dated letter with greeting and sign-off.", "H Letter\nP Dear friend,\nP Write your message here.\nP Warm regards,\nP The Nishi family") 1140 o = of_tmpl(out, o, base, 0, "W", "Meeting agenda", "Heading, attendees and a real table.", "H Meeting Agenda\nB Attendees\nP Add names here.\nT Time|Item|Lead\nT 9:00|Welcome|Host\nT 9:30|Main topic|Team\nP Notes and actions below.") 1141 o = of_tmpl(out, o, base, 1, "S", "Monthly budget", "Live =SUM plus a conditional-format rule.", "Item\tAmount\nGroceries\t400\nUtilities\t180\nTotal\t=SUM(B2:B3)\n#CF B2:B3 greaterThan 300") 1142 o = of_tmpl(out, o, base, 2, "P", "Project update", "Title and bullet slides ready to present.", "S Project Update\nB Where we are\nB What changed\nS Next steps\nB Owner and date") 1143 o = of_cat(out, o, "</div>" as *u8) 1144 // files header: count + type chips + sort links (every control is a plain link -- zero JS) 1145 o = of_cat(out, o, "<div class='fhead'><h1>Files</h1><span class='cnt'>" as *u8) 1146 o = of_catn(out, o, ne) 1147 if ne != total { o = of_cat(out, o, " of " as *u8); o = of_catn(out, o, total) } 1148 o = of_cat(out, o, "</span><span class='chips'>" as *u8) 1149 // U3 chips: Starred and Shared-with-me sit alongside the type chips. Shared is shown only when a caller is 1150 // actually signed in -- an always-visible control that can only ever be empty is a lie about the product. 1151 o = of_cat(out, o, "<a class='" as *u8) 1152 if of_seq(flt, "starred" as *u8) == 1 { o = of_cat(out, o, "on" as *u8) } 1153 o = of_cat(out, o, "' href='" as *u8); o = of_cat(out, o, base) 1154 o = of_cat(out, o, "/?filter=starred'>&starf; Starred</a>" as *u8) 1155 if authed == 1 { 1156 o = of_cat(out, o, "<a class='" as *u8) 1157 if of_seq(flt, "shared" as *u8) == 1 { o = of_cat(out, o, "on" as *u8) } 1158 o = of_cat(out, o, "' href='" as *u8); o = of_cat(out, o, base) 1159 o = of_cat(out, o, "/?filter=shared'>Shared with me</a>" as *u8) 1160 } 1161 let e0: *u8 = sys_mmap(4) 1162 e0[0] = 0 as u8 1163 var srtv: *u8 = "recent" as *u8 1164 if by_name == 1 { srtv = "name" as *u8 } 1165 var all_on: i64 = 0 1166 if tf[0] == (0 as u8) { all_on = 1 } 1167 o = of_chip(out, o, base, q, e0, srtv, "All" as *u8, all_on) 1168 o = of_chip(out, o, base, q, "doc" as *u8, srtv, "Docs" as *u8, of_seq(tf, "doc" as *u8)) 1169 o = of_chip(out, o, base, q, "sheet" as *u8, srtv, "Sheets" as *u8, of_seq(tf, "sheet" as *u8)) 1170 o = of_chip(out, o, base, q, "deck" as *u8, srtv, "Decks" as *u8, of_seq(tf, "deck" as *u8)) 1171 o = of_cat(out, o, "</span><span class='sortl'>Sort:" as *u8) 1172 o = of_chip(out, o, base, q, tf, "recent" as *u8, "Recent" as *u8, 1 - by_name) 1173 o = of_chip(out, o, base, q, tf, "name" as *u8, "Name" as *u8, by_name) 1174 o = of_cat(out, o, "</span></div>" as *u8) 1175 if ne == 0 { 1176 // no-match empty state (search/filter found nothing) 1177 o = of_cat(out, o, "<div class='empty'><h2>No files match</h2><p>" as *u8) 1178 if q[0] != (0 as u8) { o = of_cat(out, o, "Nothing named like &quot;" as *u8); o = of_esc(out, o, q); o = of_cat(out, o, "&quot;. " as *u8) } 1179 o = of_cat(out, o, "<a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/'>Clear search &amp; filters</a></p></div>" as *u8) 1180 } else { 1181 o = of_cat(out, o, "<div class='fgrid'>" as *u8) 1182 var r: i64 = 0 1183 while r < ne { 1184 let ei: i64 = ord[r] 1185 let pnm: *u8 = (names as i64 + ei * 64) as *u8 1186 o = of_cat(out, o, "<a class='fcard' href='" as *u8) 1187 o = of_cat(out, o, base); o = of_cat(out, o, "/doc/" as *u8); o = of_cat(out, o, pnm) 1188 o = of_cat(out, o, "'>" as *u8) 1189 // thumbnails for the first 60 cards keep the page bounded; the rest stay plain cards 1190 if r < 60 { o = of_thumb(out, o, root, pnm, kidx[ei], vcs[ei]) } 1191 o = of_cat(out, o, "<div class='fmeta'><div class='fico k" as *u8) 1192 o = of_catn(out, o, kidx[ei]) 1193 o = of_cat(out, o, "'>" as *u8) 1194 if kidx[ei] == 0 { o = of_cat(out, o, "W" as *u8) } 1195 if kidx[ei] == 1 { o = of_cat(out, o, "S" as *u8) } 1196 if kidx[ei] == 2 { o = of_cat(out, o, "P" as *u8) } 1197 o = of_cat(out, o, "</div><span class='nm'><b>" as *u8) 1198 o = of_esc(out, o, pnm) 1199 o = of_cat(out, o, "</b><span>v" as *u8) 1200 o = of_catn(out, o, vcs[ei]) 1201 o = of_cat(out, o, " &middot; " as *u8) 1202 o = of_ago(out, o, uss[ei]) 1203 o = of_cat(out, o, "</span></span></div></a>" as *u8) 1204 r = r + 1 1205 } 1206 o = of_cat(out, o, "</div>" as *u8) 1207 if ne == 256 { o = of_cat(out, o, "<p class='hint'>Showing the first 256 files.</p>" as *u8) } 1208 } 1209 o = of_cat(out, o, "</main>" as *u8) 1210 o = of_page_foot(out, o) 1211 return o 1212} 1213// ---- version DIFF (leverages the never-lose store: every version's spec.txt is on disk) ---- 1214func of_lineeq(a: *u8, b: *u8) -> i64 { 1215 var i: i64 = 0 1216 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 1217 if b[i] != (0 as u8) { return 0 } 1218 return 1 1219} 1220// split buf[0,n) into NUL-terminated lines in place; store start pointers in lp[]; return count (<=maxl). Caller sets buf[n]=0. 1221func of_split_lines(buf: *u8, n: i64, lp: *i64, maxl: i64) -> i64 { 1222 var c: i64 = 0 1223 var i: i64 = 0 1224 while i < n { 1225 if c >= maxl { return c } 1226 lp[c] = (buf as i64) + i 1227 c = c + 1 1228 while i < n { if buf[i] == (10 as u8) { break } i = i + 1 } 1229 if i < n { buf[i] = 0 as u8; i = i + 1 } 1230 } 1231 return c 1232} 1233func of_read_version_spec(root: *u8, name: *u8, vn: i64, buf: *u8, cap: i64) -> i64 { 1234 let vd: *u8 = sys_mmap(512) 1235 of_vdir(root, name, vn, vd) 1236 let sp: *u8 = sys_mmap(600) 1237 var so: i64 = of_cat(sp, 0, vd); so = of_cat(sp, so, "/spec.txt" as *u8); sp[so] = 0 as u8 1238 let n: i64 = of_read_file(sp, buf, cap) 1239 if n > 0 { buf[n] = 0 as u8; return n } 1240 buf[0] = 0 as u8; return 0 1241} 1242// render an LCS line-diff of specA vs specB into out. added=in B not A (green), removed=in A not B (red). 1243func of_render_diff(out: *u8, off: i64, bufa: *u8, na_bytes: i64, bufb: *u8, nb_bytes: i64) -> i64 { 1244 let MAXL: i64 = 400 1245 let la: *i64 = sys_mmap(MAXL * 8) as *i64 1246 let lb: *i64 = sys_mmap(MAXL * 8) as *i64 1247 let na: i64 = of_split_lines(bufa, na_bytes, la, MAXL) 1248 let nb: i64 = of_split_lines(bufb, nb_bytes, lb, MAXL) 1249 let W: i64 = nb + 1 1250 let dp: *i64 = sys_mmap((na + 1) * (nb + 1) * 8) as *i64 1251 var i: i64 = na 1252 while i >= 0 { 1253 var j: i64 = nb 1254 while j >= 0 { 1255 if i == na { dp[i*W + j] = 0 } else { if j == nb { dp[i*W + j] = 0 } else { 1256 if of_lineeq(la[i] as *u8, lb[j] as *u8) == 1 { dp[i*W + j] = dp[(i+1)*W + (j+1)] + 1 } 1257 else { let d1: i64 = dp[(i+1)*W + j]; let d2: i64 = dp[i*W + (j+1)]; if d1 >= d2 { dp[i*W + j] = d1 } else { dp[i*W + j] = d2 } } 1258 } } 1259 j = j - 1 1260 } 1261 i = i - 1 1262 } 1263 var o: i64 = of_cat(out, off, "<div class='diff'>" as *u8) 1264 var add: i64 = 0; var del: i64 = 0 1265 var a: i64 = 0; var b: i64 = 0 1266 var go: i64 = 1 1267 while go == 1 { 1268 if a < na { if b < nb { 1269 if of_lineeq(la[a] as *u8, lb[b] as *u8) == 1 { 1270 o = of_cat(out, o, "<div class='dkeep'>&nbsp;&nbsp;" as *u8); o = of_esc(out, o, la[a] as *u8); o = of_cat(out, o, "</div>" as *u8); a = a + 1; b = b + 1 1271 } else { if dp[(a+1)*W + b] >= dp[a*W + (b+1)] { 1272 o = of_cat(out, o, "<div class='ddel'>&minus;&nbsp;" as *u8); o = of_esc(out, o, la[a] as *u8); o = of_cat(out, o, "</div>" as *u8); a = a + 1; del = del + 1 1273 } else { 1274 o = of_cat(out, o, "<div class='dadd'>+&nbsp;" as *u8); o = of_esc(out, o, lb[b] as *u8); o = of_cat(out, o, "</div>" as *u8); b = b + 1; add = add + 1 1275 } } 1276 } else { 1277 o = of_cat(out, o, "<div class='ddel'>&minus;&nbsp;" as *u8); o = of_esc(out, o, la[a] as *u8); o = of_cat(out, o, "</div>" as *u8); a = a + 1; del = del + 1 1278 } } else { if b < nb { 1279 o = of_cat(out, o, "<div class='dadd'>+&nbsp;" as *u8); o = of_esc(out, o, lb[b] as *u8); o = of_cat(out, o, "</div>" as *u8); b = b + 1; add = add + 1 1280 } else { go = 0 } } 1281 } 1282 o = of_cat(out, o, "</div><p class='sub' style='margin-top:8px'><b>" as *u8); o = of_catn(out, o, add); o = of_cat(out, o, "</b> line(s) added, <b>" as *u8); o = of_catn(out, o, del); o = of_cat(out, o, "</b> removed.</p>" as *u8) 1283 return o 1284} 1285func of_diffpage(root: *u8, base: *u8, name: *u8, va: i64, vb: i64, out: *u8, cap: i64) -> i64 { 1286 let kb: *u8 = sys_mmap(64) 1287 let vc: i64 = of_manifest_count(root, name, kb, 64) 1288 if vc <= 0 { return 0 - 1 } 1289 if va < 1 { return 0 - 1 } 1290 if vb < 1 { return 0 - 1 } 1291 if va > vc { return 0 - 1 } 1292 if vb > vc { return 0 - 1 } 1293 let ba: *u8 = sys_mmap(131072) 1294 let bb: *u8 = sys_mmap(131072) 1295 let nab: i64 = of_read_version_spec(root, name, va, ba, 131071) 1296 let nbb: i64 = of_read_version_spec(root, name, vb, bb, 131071) 1297 let eqd: *u8 = sys_mmap(4) 1298 eqd[0] = 0 as u8 1299 var o: i64 = of_shell_top(out, 0, name, base, eqd) 1300 o = of_cat(out, o, "<main id='main' class='wrap'><p class='crumb'><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/doc/" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "'>&larr; " as *u8); o = of_esc(out, o, name); o = of_cat(out, o, "</a></p><h1>Changes: v" as *u8) 1301 o = of_catn(out, o, va); o = of_cat(out, o, " &rarr; v" as *u8); o = of_catn(out, o, vb) 1302 o = of_cat(out, o, "</h1><p class='sub'>Every version is kept forever &mdash; this compares the two specs line by line.</p>\n<div class='card'>" as *u8) 1303 o = of_render_diff(out, o, ba, nab, bb, nbb) 1304 o = of_cat(out, o, "</div></main>\n" as *u8) 1305 o = of_page_foot(out, o) 1306 return o 1307} 1308func of_docpage(root: *u8, base: *u8, name: *u8, out: *u8, cap: i64) -> i64 { 1309 let kb: *u8 = sys_mmap(64) 1310 let vc: i64 = of_manifest_count(root, name, kb, 64) 1311 if vc <= 0 { return 0 - 1 } 1312 let ki: i64 = of_kind_idx(kb) 1313 var ks: i64 = ki 1314 if ks < 0 { ks = 0 } 1315 let eq: *u8 = sys_mmap(4) 1316 eq[0] = 0 as u8 1317 var o: i64 = of_shell_top(out, 0, name, base, eq) 1318 o = of_cat(out, o, "<main id='main' class='wrap'><p class='crumb'><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/'>&larr; All files</a></p><h1>" as *u8) 1319 o = of_esc(out, o, name) 1320 o = of_cat(out, o, " <span class='k k" as *u8); o = of_catn(out, o, ks); o = of_cat(out, o, "'>" as *u8); o = of_esc(out, o, kb) 1321 o = of_cat(out, o, "</span> <span class='stamp'>Saved v" as *u8) 1322 o = of_catn(out, o, vc) 1323 o = of_cat(out, o, " &middot; " as *u8) 1324 o = of_ago(out, o, of_manifest_last_us(root, name)) 1325 o = of_cat(out, o, "</span></h1><p class='sub'>" as *u8) 1326 o = of_catn(out, o, vc) 1327 o = of_cat(out, o, " version(s), additive &mdash; saving creates v" as *u8) 1328 o = of_catn(out, o, vc + 1) 1329 o = of_cat(out, o, ", earlier versions stay forever.</p>\n" as *u8) 1330 let vd: *u8 = sys_mmap(512) 1331 of_vdir(root, name, vc, vd) 1332 let sp: *u8 = sys_mmap(600) 1333 var so: i64 = of_cat(sp, 0, vd); so = of_cat(sp, so, "/spec.txt" as *u8); sp[so] = 0 as u8 1334 let spec: *u8 = sys_mmap(131072) 1335 let sl: i64 = of_read_file(sp, spec, 131071) 1336 if sl > 0 { spec[sl] = 0 as u8 } 1337 // ---- the visual editor card: toolbar + WYSIWYG surface + raw-spec fallback, all in one form ---- 1338 o = of_cat(out, o, "<div class='card'>" as *u8) 1339 o = of_toolbar(out, o, ks) 1340 o = of_cat(out, o, "<form id='savef' method='post' action='" as *u8) 1341 o = of_cat(out, o, base) 1342 o = of_cat(out, o, "/save'><input type='hidden' name='kind' value='" as *u8) 1343 o = of_cat(out, o, kb) 1344 o = of_cat(out, o, "'><input type='hidden' name='name' value='" as *u8) 1345 o = of_cat(out, o, name) 1346 o = of_cat(out, o, "'>" as *u8) 1347 if ks == 0 { o = of_render_doc(out, o, spec, sl) } 1348 if ks == 1 { o = of_render_sheet(out, o, spec, sl) } 1349 if ks == 2 { o = of_render_deck(out, o, spec, sl) } 1350 o = of_cat(out, o, "<details id='rawd' class='rawwrap' open><summary>Edit raw spec</summary><textarea id='specta' name='spec'>" as *u8) 1351 if sl > 0 { o = of_esc(out, o, spec) } 1352 o = of_cat(out, o, "</textarea></details>" as *u8) 1353 o = of_cat(out, o, "<p><button type='submit' class='save'>Save as v" as *u8) 1354 o = of_catn(out, o, vc + 1) 1355 o = of_cat(out, o, "</button> <span id='savest' class='hint'></span></p></form></div>\n" as *u8) 1356 if ks == 0 { 1357 o = of_cat(out, o, "<div class='card'><h2 style='margin:0 0 8px'>&#10024; AI draft</h2><p class='hint' style='margin:0 0 10px'>Continue this document with our OWN sovereign no-float 0.5B model, on our own hardware &mdash; zero OpenAI. The draft is appended as a NEW version you can edit, diff or restore. <b>Experimental</b> (0.5B is small &mdash; quality is rough).</p><form method='post' action='" as *u8) 1358 o = of_cat(out, o, base) 1359 o = of_cat(out, o, "/ai'><input type='hidden' name='name' value='" as *u8) 1360 o = of_cat(out, o, name) 1361 o = of_cat(out, o, "'><button type='submit' class='ghost'>&#10024; Continue with AI</button></form></div>\n" as *u8) 1362 // ---- OF-A4 AGENT MODE card: plan -> execute -> refine, one turn per click ---- 1363 let agb: *u8 = sys_mmap(8192) 1364 let agn: i64 = of_agent_read(root, name, agb, 8000) 1365 let agsteps: i64 = of_agent_tagcount(agb, agn, 83) 1366 let agdone: i64 = of_agent_done(agb, agn) 1367 o = of_cat(out, o, "<div class='card'><h2 style='margin:0 0 8px'>&#129302; Agent mode</h2><p class='hint' style='margin:0 0 10px'>Give it a goal and it <b>plans, executes and refines</b> multi-step work on this document &mdash; on OUR own sovereign model, zero cloud. Each step lands as a <b>new version</b>, so the agent's whole trajectory stays diffable and restorable. One click = one turn (each model turn takes several seconds). <b>Experimental</b> (0.5B is small &mdash; quality is rough).</p>" as *u8) 1368 if agn <= 0 { 1369 o = of_cat(out, o, "<form method='post' action='" as *u8) 1370 o = of_cat(out, o, base) 1371 o = of_cat(out, o, "/agent'><input type='hidden' name='name' value='" as *u8) 1372 o = of_cat(out, o, name) 1373 o = of_cat(out, o, "'><input type='text' name='goal' placeholder='e.g. add a section on summer plans and a closing' style='width:100%;margin-bottom:8px'><button type='submit' class='ghost'>&#129302; Plan it</button></form>" as *u8) 1374 } else { 1375 let agg: *u8 = sys_mmap(512) 1376 of_agent_tagline(agb, agn, 71, 0, agg, 512) 1377 o = of_cat(out, o, "<p style='margin:0 0 6px'><b>Goal:</b> " as *u8) 1378 o = of_esc(out, o, agg) 1379 o = of_cat(out, o, "</p><ol class='agentplan' style='margin:0 0 10px 18px'>" as *u8) 1380 let agsb: *u8 = sys_mmap(256) 1381 var agi: i64 = 0 1382 while agi < agsteps { 1383 of_agent_tagline(agb, agn, 83, agi, agsb, 256) 1384 o = of_cat(out, o, "<li>" as *u8) 1385 if agi < agdone { o = of_cat(out, o, "<span class='cnt'>&#10003;</span> " as *u8) } 1386 o = of_esc(out, o, agsb) 1387 o = of_cat(out, o, "</li>" as *u8) 1388 agi = agi + 1 1389 } 1390 o = of_cat(out, o, "</ol>" as *u8) 1391 if agdone > agsteps { 1392 o = of_cat(out, o, "<p class='hint' style='margin:0 0 10px'>&#10003; <b>Run complete</b> &mdash; every step drafted and refined. Give a new goal to start another run.</p><form method='post' action='" as *u8) 1393 o = of_cat(out, o, base) 1394 o = of_cat(out, o, "/agent'><input type='hidden' name='name' value='" as *u8) 1395 o = of_cat(out, o, name) 1396 o = of_cat(out, o, "'><input type='text' name='goal' placeholder='new goal' style='width:100%;margin-bottom:8px'><button type='submit' class='ghost'>&#129302; Plan again</button></form>" as *u8) 1397 } else { 1398 o = of_cat(out, o, "<p class='hint' style='margin:0 0 10px'>Turn " as *u8) 1399 o = of_catn(out, o, agdone + 1) 1400 o = of_cat(out, o, " of " as *u8) 1401 o = of_catn(out, o, agsteps + 1) 1402 o = of_cat(out, o, " (the last turn is the refine pass).</p><form method='post' action='" as *u8) 1403 o = of_cat(out, o, base) 1404 o = of_cat(out, o, "/agent'><input type='hidden' name='name' value='" as *u8) 1405 o = of_cat(out, o, name) 1406 o = of_cat(out, o, "'><button type='submit' class='ghost'>&#9654; " as *u8) 1407 if agdone < agsteps { o = of_cat(out, o, "Run next step" as *u8) } else { o = of_cat(out, o, "Run final refine" as *u8) } 1408 o = of_cat(out, o, "</button></form>" as *u8) 1409 } 1410 } 1411 o = of_cat(out, o, "</div>\n" as *u8) 1412 } 1413 // OF-A2 (sheets) / OF-A3 (decks): the same sovereign seat, in each artifact's own grammar. Agent mode stays 1414 // doc-only for now (it appends prose), so these get the single-turn card, not the plan/execute/refine loop. 1415 if ks != 0 { 1416 o = of_cat(out, o, "<div class='card'><h2 style='margin:0 0 8px'>&#10024; " as *u8) 1417 if ks == 1 { o = of_cat(out, o, "AI insight" as *u8) } else { o = of_cat(out, o, "AI slide" as *u8) } 1418 o = of_cat(out, o, "</h2><p class='hint' style='margin:0 0 10px'>" as *u8) 1419 if ks == 1 { 1420 o = of_cat(out, o, "Ask our OWN sovereign model to read this grid and add one insight as a new row &mdash; zero cloud. It lands as a NEW version you can edit, diff or restore." as *u8) 1421 } else { 1422 o = of_cat(out, o, "Ask our OWN sovereign model to draft the next slide (title + bullet) from the deck so far &mdash; zero cloud. It lands as a NEW version you can edit, diff or restore." as *u8) 1423 } 1424 o = of_cat(out, o, " <b>Experimental</b> (0.5B is small &mdash; quality is rough).</p><form method='post' action='" as *u8) 1425 o = of_cat(out, o, base) 1426 o = of_cat(out, o, "/ai'><input type='hidden' name='name' value='" as *u8) 1427 o = of_cat(out, o, name) 1428 o = of_cat(out, o, "'><button type='submit' class='ghost'>&#10024; " as *u8) 1429 if ks == 1 { o = of_cat(out, o, "Add an AI insight" as *u8) } else { o = of_cat(out, o, "Draft the next slide" as *u8) } 1430 o = of_cat(out, o, "</button></form></div>\n" as *u8) 1431 } 1432 // U3: star + folder controls. Zero-JS forms, same additive spirit as everything else -- neither touches 1433 // the spec or the version chain, so organising a file can never damage its content. 1434 o = of_cat(out, o, "<div class='card'><h2 style='margin:0 0 8px'>Organise</h2><p class='hint' style='margin:0 0 10px'>Star it to pin it to the top of your library, or file it in a folder. Neither changes the document or its history.</p><form method='post' action='" as *u8) 1435 o = of_cat(out, o, base) 1436 o = of_cat(out, o, "/star' style='display:inline'><input type='hidden' name='name' value='" as *u8) 1437 o = of_cat(out, o, name) 1438 o = of_cat(out, o, "'><button type='submit' class='ghost'>" as *u8) 1439 if of_starred(root, name) == 1 { o = of_cat(out, o, "&starf; Starred (click to unstar)" as *u8) } else { o = of_cat(out, o, "&star; Star this file" as *u8) } 1440 o = of_cat(out, o, "</button></form> <form method='post' action='" as *u8) 1441 o = of_cat(out, o, base) 1442 o = of_cat(out, o, "/folder' style='display:inline'><input type='hidden' name='name' value='" as *u8) 1443 o = of_cat(out, o, name) 1444 o = of_cat(out, o, "'><input type='text' name='folder' placeholder='folder' value='" as *u8) 1445 let fcur: *u8 = sys_mmap(64) 1446 of_folder_get(root, name, fcur, 64) 1447 o = of_esc(out, o, fcur) 1448 o = of_cat(out, o, "'><button type='submit' class='ghost'>File it</button></form></div> 1449" as *u8) 1450 o = of_cat(out, o, "<div class='card'><h2 style='margin:0 0 8px'>Versions</h2><div class='tablewrap'><table><thead><tr><th>Version</th><th>Changes</th><th>Preview</th><th>Download</th><th>Restore</th><th>Sign</th></tr></thead><tbody>" as *u8) 1451 var v: i64 = vc 1452 while v >= 1 { 1453 o = of_cat(out, o, "<tr><td><b>v" as *u8); o = of_catn(out, o, v) 1454 o = of_cat(out, o, "</b>" as *u8) 1455 if of_manifest_is_auto(root, name, v) == 1 { o = of_cat(out, o, " <span class='cnt'>(auto)</span>" as *u8) } 1456 o = of_cat(out, o, "</td><td>" as *u8) 1457 if v >= 2 { o = of_cat(out, o, "<a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/diff/" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "/" as *u8); o = of_catn(out, o, v - 1); o = of_cat(out, o, "/" as *u8); o = of_catn(out, o, v); o = of_cat(out, o, "'>vs v" as *u8); o = of_catn(out, o, v - 1); o = of_cat(out, o, "</a>" as *u8) } 1458 else { o = of_cat(out, o, "&mdash;" as *u8) } 1459 o = of_cat(out, o, "</td><td><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/preview/" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "/v" as *u8); o = of_catn(out, o, v) 1460 o = of_cat(out, o, "'>preview</a></td><td><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/file/" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "/v" as *u8); o = of_catn(out, o, v) 1461 o = of_cat(out, o, "'>" as *u8); o = of_esc(out, o, name); o = of_cat(out, o, "." as *u8); o = of_cat(out, o, of_ext(ks)); o = of_cat(out, o, "</a></td><td>" as *u8) 1462 if v < vc { 1463 o = of_cat(out, o, "<form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/restore' style='margin:0'><input type='hidden' name='name' value='" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "'><input type='hidden' name='version' value='" as *u8); o = of_catn(out, o, v); o = of_cat(out, o, "'><button type='submit' class='ghost' title='Save this version as the newest (nothing is lost)'>Restore</button></form>" as *u8) 1464 } else { o = of_cat(out, o, "<span class='cnt'>current</span>" as *u8) } 1465 o = of_cat(out, o, "</td><td>" as *u8) 1466 o = of_sign_cell(out, o, root, base, name, v) 1467 o = of_cat(out, o, "</td></tr>" as *u8) 1468 v = v - 1 1469 } 1470 o = of_cat(out, o, "</tbody></table></div></div></main>\n<script src='" as *u8) 1471 o = of_cat(out, o, base) 1472 o = of_cat(out, o, "/app.js'></script>\n" as *u8) 1473 o = of_page_foot(out, o) 1474 return o 1475} 1476func of_err(out: *u8, status: *u8, msg: *u8) -> i64 { 1477 // body = "LOUD: " + msg + "\n" (6 + len(msg) + 1). Emit Content-Length + Connection: close so a STRICT 1478 // CL-stop client (our own nx_https TLS stack / nx_office_live_verify) can frame the error without hanging. 1479 let bl: i64 = 6 + of_slen(msg) + 1 1480 var o: i64 = of_cat(out, 0, "HTTP/1.1 " as *u8) 1481 o = of_cat(out, o, status) 1482 o = of_cat(out, o, "\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: " as *u8) 1483 o = of_catn(out, o, bl) 1484 o = of_cat(out, o, "\r\nConnection: close\r\n\r\nLOUD: " as *u8) 1485 o = of_cat(out, o, msg) 1486 o = of_catc(out, o, 10) 1487 return o 1488} 1489// ---- IN-APP AI (the marquee): draft with OUR OWN sovereign no-float 0.5B LLM served on loopback :11434 ---- 1490// HONEST: it is a 0.5B integer model -- draft quality is EXPERIMENTAL, not GPT/Copilot-class. The point is 1491// sovereign convergence: our office drafting off our own model on our own hardware, zero OpenAI. Graceful: 1492// if the seat is down, the caller returns a LOUD 503 (never an office error). 1493// extract the FIRST "content":"..." value (JSON-unescaped) from buf into out; returns length or -1 if absent. 1494func of_extract_json_content(buf: *u8, n: i64, out: *u8, cap: i64) -> i64 { 1495 let key: *u8 = "\"content\":\"" as *u8 1496 var i: i64 = 0 1497 var found: i64 = 0 - 1 1498 while i + 11 <= n { 1499 var m: i64 = 1; var j: i64 = 0 1500 while j < 11 { if buf[i+j] != key[j] { m = 0; j = 11 } else { j = j + 1 } } 1501 if m == 1 { found = i + 11; i = n } else { i = i + 1 } 1502 } 1503 if found < 0 { return 0 - 1 } 1504 var o: i64 = 0 1505 var k: i64 = found 1506 var go: i64 = 1 1507 while go == 1 { 1508 if k >= n { go = 0 } else { 1509 let c: i64 = buf[k] as i64 1510 if c == 34 { go = 0 } else { 1511 if c == 92 { 1512 k = k + 1 1513 if k < n { 1514 let e: i64 = buf[k] as i64 1515 if e == 110 { if o < cap-1 { out[o] = 10 as u8; o = o + 1 } } else { 1516 if e == 116 { if o < cap-1 { out[o] = 9 as u8; o = o + 1 } } else { 1517 if e == 34 { if o < cap-1 { out[o] = 34 as u8; o = o + 1 } } else { 1518 if e == 92 { if o < cap-1 { out[o] = 92 as u8; o = o + 1 } } else { 1519 if o < cap-1 { out[o] = buf[k]; o = o + 1 } } } } } 1520 } 1521 k = k + 1 1522 } else { 1523 if o < cap-1 { out[o] = buf[k]; o = o + 1 } 1524 k = k + 1 1525 } } 1526 } 1527 } 1528 out[o] = 0 as u8 1529 return o 1530} 1531// flatten a doc spec (H/B/I/P lines; T table rows) into plain running text for the LLM prompt (strip the 2-char 1532// kind prefix, '|' table cells -> spaces). Keeps only the tail (last ~cap chars) since the 0.5B context is small. 1533func of_spec_to_text(spec: *u8, sl: i64, out: *u8, cap: i64) -> i64 { 1534 let tmp: *u8 = sys_mmap(sl + 16) 1535 var to: i64 = 0 1536 var i: i64 = 0 1537 while i < sl { 1538 var e: i64 = i 1539 while e < sl { if spec[e] == (10 as u8) { break } e = e + 1 } 1540 var cs: i64 = i 1541 if e >= i + 2 { if spec[i+1] == (32 as u8) { cs = i + 2 } } 1542 var k: i64 = cs 1543 while k < e { let c: i64 = spec[k] as i64; if c == 124 { tmp[to] = 32 as u8 } else { tmp[to] = spec[k] } to = to + 1; k = k + 1 } 1544 tmp[to] = 32 as u8; to = to + 1 1545 i = e + 1 1546 } 1547 // keep the tail 1548 var start: i64 = 0 1549 if to > cap { start = to - cap } 1550 var oo: i64 = 0 1551 var t: i64 = start 1552 while t < to { if oo < cap - 1 { out[oo] = tmp[t]; oo = oo + 1 } t = t + 1 } 1553 out[oo] = 0 as u8 1554 return oo 1555} 1556// call our sovereign LLM seat (POST /complete on 127.0.0.1:11434) to continue `prompt`. Fills out with the 1557// completion (JSON-unescaped); returns length, or <0 on conn-fail / non-200 / empty (caller -> graceful 503). 1558// max_tokens is a PARAMETER (of_llm_complete keeps the proven 24 default) because agent mode needs a longer 1559// budget for its PLAN turn than for a step turn. Keep every value small enough that ONE call finishes well 1560// under the edge's ~15s proxy timeout -- measured ~0.29s/token, so 32 tokens ~= 9.3s is the safe ceiling. 1561func of_llm_complete_n(prompt: *u8, plen: i64, out: *u8, cap: i64, maxtok: i64) -> i64 { 1562 let bcap: i64 = plen * 2 + 256 1563 let jb: *u8 = sys_mmap(bcap) 1564 var bo: i64 = of_cat(jb, 0, "{\"content\":\"" as *u8) 1565 var i: i64 = 0 1566 while i < plen { 1567 let c: i64 = prompt[i] as i64 1568 if c == 34 { jb[bo] = 92 as u8; bo = bo + 1; jb[bo] = 34 as u8; bo = bo + 1 } else { 1569 if c == 92 { jb[bo] = 92 as u8; bo = bo + 1; jb[bo] = 92 as u8; bo = bo + 1 } else { 1570 if c == 10 { jb[bo] = 92 as u8; bo = bo + 1; jb[bo] = 110 as u8; bo = bo + 1 } else { 1571 if c == 9 { jb[bo] = 32 as u8; bo = bo + 1 } else { 1572 if c == 13 { } else { 1573 if c < 32 { jb[bo] = 32 as u8; bo = bo + 1 } else { jb[bo] = prompt[i]; bo = bo + 1 } } } } } } 1574 i = i + 1 1575 } 1576 bo = of_cat(jb, bo, "\",\"max_tokens\":" as *u8) 1577 bo = of_catn(jb, bo, maxtok) 1578 bo = of_catc(jb, bo, 125) 1579 jb[bo] = 0 as u8 1580 let addr: *u8 = sys_mmap(16) 1581 nx_http_client_sockaddr_ipv4(addr, 127, 0, 0, 1, 11434) 1582 let fd: i64 = sys_socket(2, 1, 0) 1583 if fd < 0 { return 0 - 1 } 1584 if nx_connect_bounded(fd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0 - 2 } 1585 sys_set_socket_timeout(fd, 14) 1586 let ct: *u8 = "application/json" as *u8 1587 let req: *u8 = sys_mmap(8192 + bo) 1588 let reqlen: i64 = nx_http_client_build_request_post("/complete" as *u8, 9, "localhost" as *u8, 9, ct, 16, jb, bo, req) 1589 sys_write(fd, req, reqlen) 1590 let resp: *u8 = sys_mmap(262144) 1591 var rn: i64 = 0 1592 var go: i64 = 1 1593 while go == 1 { if rn >= 262143 { go = 0 } else { let r: i64 = sys_read(fd, (resp as i64 + rn) as *u8, 262143 - rn); if r <= 0 { go = 0 } else { rn = rn + r } } } 1594 sys_close(fd) 1595 if rn < 15 { return 0 - 3 } 1596 if (resp[9] as i64) != 50 { return 0 - 4 } 1597 if (resp[10] as i64) != 48 { return 0 - 4 } 1598 if (resp[11] as i64) != 48 { return 0 - 4 } 1599 resp[rn] = 0 as u8 1600 let cl: i64 = of_extract_json_content(resp, rn, out, cap) 1601 if cl <= 0 { return 0 - 5 } 1602 return cl 1603} 1604func of_llm_complete(prompt: *u8, plen: i64, out: *u8, cap: i64) -> i64 { 1605 return of_llm_complete_n(prompt, plen, out, cap, 24) 1606} 1607// OF-A2 / OF-A3: each kind gets its OWN prompt builder rather than one function with a kind flag, so the 1608// census can needle a DEFINITION per axis (its own anti-faking law: a comment mentioning a bare name must 1609// never flip an axis) and each stays independently editable. 1610func of_ai_prompt_sheet(ptext: *u8, out: *u8) -> i64 { 1611 var o: i64 = of_cat(out, 0, "This is a spreadsheet, tab separated. Data: " as *u8) 1612 o = of_cat(out, o, ptext) 1613 o = of_cat(out, o, " . State one short insight about this data:" as *u8) 1614 out[o] = 0 as u8 1615 return o 1616} 1617func of_ai_prompt_deck(ptext: *u8, out: *u8) -> i64 { 1618 var o: i64 = of_cat(out, 0, "Slides so far: " as *u8) 1619 o = of_cat(out, o, ptext) 1620 o = of_cat(out, o, " . Write the next slide as a title, then one bullet:" as *u8) 1621 out[o] = 0 as u8 1622 return o 1623} 1624 1625// ================= OF-A4 AGENT MODE -- multi-step PLAN -> EXECUTE -> REFINE ========================= 1626// The 2025/2026 headline differentiator the SOTA bar names (M365 Copilot "Agent Mode" GA 2026-04-22: 1627// Copilot plans, executes and refines MULTI-STEP work in the app). Ours runs on OUR OWN sovereign seat. 1628// 1629// WHY IT IS STEP-DRIVEN, NOT A SINGLE LONG CALL: one LLM turn costs ~7-10s and the edge proxy times out at 1630// ~15s. A 4-step agent in one request would ALWAYS exceed it. So each POST /office/agent advances EXACTLY 1631// ONE turn and persists its state; the loop is driven by repeated POSTs. That is a real constraint honestly 1632// handled, not a reduced capability -- the agent is still multi-step, state-carrying and resumable. 1633// 1634// WHERE THE EXCEEDS IS: every executed step lands as a NEW ADDITIVE VERSION through of_save, so the entire 1635// agent trajectory is diffable and restorable. The cloud leaders' agent steps are ephemeral -- you get the 1636// final artifact and the reasoning is gone. Ours is content-addressed history you can walk backwards. 1637// 1638// State lives in a SIDECAR <root>/<name>/agent.txt so the document spec stays PURE CONTENT (no new spec line 1639// kinds = no renderer risk, no format migration). Line-based, same idiom as the spec: 1640// G <goal> one line, the operator's goal 1641// S <step> one line per planned step, in order 1642// D <n> how many turns are DONE. n in 0..steps = executing; n > steps = refined + complete. 1643func of_agent_path(root: *u8, name: *u8, out: *u8) -> i64 { 1644 var o: i64 = of_cat(out, 0, root); o = of_cat(out, o, "/" as *u8); o = of_cat(out, o, name) 1645 o = of_cat(out, o, "/agent.txt" as *u8); out[o] = 0 as u8 1646 return o 1647} 1648func of_agent_read(root: *u8, name: *u8, buf: *u8, cap: i64) -> i64 { 1649 let p: *u8 = sys_mmap(512) 1650 of_agent_path(root, name, p) 1651 return of_read_file(p, buf, cap) 1652} 1653func of_agent_write(root: *u8, name: *u8, buf: *u8, n: i64) -> i64 { 1654 let p: *u8 = sys_mmap(512) 1655 of_agent_path(root, name, p) 1656 return of_write_file(p, buf, n) 1657} 1658// count the lines whose FIRST byte is `tag` (tags: 71='G' 83='S' 68='D') 1659func of_agent_tagcount(buf: *u8, n: i64, tag: i64) -> i64 { 1660 var c: i64 = 0 1661 var i: i64 = 0 1662 var bol: i64 = 1 1663 while i < n { 1664 if bol == 1 { if (buf[i] as i64) == tag { c = c + 1 } } 1665 if buf[i] == (10 as u8) { bol = 1 } else { bol = 0 } 1666 i = i + 1 1667 } 1668 return c 1669} 1670// copy the body of the idx-th (0-based) line carrying `tag` into out; returns its length (0 = no such line) 1671func of_agent_tagline(buf: *u8, n: i64, tag: i64, idx: i64, out: *u8, cap: i64) -> i64 { 1672 var seen: i64 = 0 1673 var i: i64 = 0 1674 var bol: i64 = 1 1675 while i < n { 1676 if bol == 1 { 1677 if (buf[i] as i64) == tag { 1678 if seen == idx { 1679 var s: i64 = i + 1 1680 if s < n { if buf[s] == (32 as u8) { s = s + 1 } } 1681 var o: i64 = 0 1682 while s < n { 1683 if buf[s] == (10 as u8) { s = n } else { 1684 if o < cap - 1 { out[o] = buf[s]; o = o + 1 } 1685 s = s + 1 } 1686 } 1687 out[o] = 0 as u8 1688 return o 1689 } 1690 seen = seen + 1 1691 } 1692 } 1693 if buf[i] == (10 as u8) { bol = 1 } else { bol = 0 } 1694 i = i + 1 1695 } 1696 out[0] = 0 as u8 1697 return 0 1698} 1699func of_agent_done(buf: *u8, n: i64) -> i64 { 1700 let t: *u8 = sys_mmap(32) 1701 if of_agent_tagline(buf, n, 68, 0, t, 32) <= 0 { return 0 } 1702 return of_atoi(t) 1703} 1704// Turn ONE free-text LLM completion into at most 4 plan steps. Splits on newlines first; if that yields 1705// fewer than 2 steps, falls back to splitting on ". " so a single-line reply still becomes a real plan. 1706// Leading list punctuation (digits, '.', ')', '-', '*', spaces) is stripped so "1. Draft intro" -> "Draft intro". 1707// Emits "S <step>\n" lines into out. Returns how many steps were written (0 = the model gave us nothing usable). 1708func of_agent_plan_parse(comp: *u8, cl: i64, out: *u8, cap: i64) -> i64 { 1709 var steps: i64 = 0 1710 var o: i64 = 0 1711 var ph: i64 = 0 1712 while ph < 2 { 1713 steps = 0 1714 o = 0 1715 var i: i64 = 0 1716 while i < cl { 1717 if steps >= 4 { i = cl } else { 1718 // find the end of this chunk: newline always ends it; in phase 1 ". " ends it too 1719 var e: i64 = i 1720 var scan: i64 = 1 1721 while scan == 1 { 1722 if e >= cl { scan = 0 } else { 1723 if comp[e] == (10 as u8) { scan = 0 } else { 1724 var brk: i64 = 0 1725 if ph == 1 { 1726 if comp[e] == (46 as u8) { 1727 if e + 1 < cl { if comp[e+1] == (32 as u8) { brk = 1 } } 1728 } 1729 } 1730 if brk == 1 { scan = 0 } else { e = e + 1 } 1731 } 1732 } 1733 } 1734 // strip leading list punctuation + spaces: "1. Draft intro" -> "Draft intro" 1735 var s: i64 = i 1736 var strip: i64 = 1 1737 while strip == 1 { 1738 if s >= e { strip = 0 } else { 1739 let c: i64 = comp[s] as i64 1740 if c == 32 { s = s + 1 } else { 1741 if c == 46 { s = s + 1 } else { 1742 if c == 41 { s = s + 1 } else { 1743 if c == 45 { s = s + 1 } else { 1744 if c == 42 { s = s + 1 } else { 1745 if c >= 48 { if c <= 57 { s = s + 1 } else { strip = 0 } } else { strip = 0 } } } } } } 1746 } 1747 } 1748 // keep it only if real text survives (>= 4 chars) and it fits the buffer 1749 if e - s >= 4 { 1750 if o + (e - s) + 8 < cap { 1751 o = of_cat(out, o, "S " as *u8) 1752 var k: i64 = s 1753 var w: i64 = 0 1754 while k < e { 1755 if w < 120 { 1756 let c2: i64 = comp[k] as i64 1757 if c2 == 9 { out[o] = 32 as u8 } else { if c2 == 13 { out[o] = 32 as u8 } else { out[o] = comp[k] } } 1758 o = o + 1; w = w + 1 1759 } 1760 k = k + 1 1761 } 1762 o = of_catc(out, o, 10) 1763 steps = steps + 1 1764 } 1765 } 1766 i = e + 1 1767 } 1768 } 1769 // phase 0 (newline split) wins if it found a real multi-step plan; else retry splitting sentences 1770 if steps >= 2 { ph = 2 } else { ph = ph + 1 } 1771 } 1772 out[o] = 0 as u8 1773 return steps 1774} 1775// Insert Content-Length before the header terminator so a STRICT HTTP client (the sovereign Nishi Browser) 1776// can frame the body. Static docroot files send it; our HTML pages (of_page_top) did NOT, so the in-browser 1777// GET of /office failed to frame after a clean TLS handshake (Waterfox tolerates it by reading until close). 1778// out holds a full "HTTP/.. \r\n<headers>\r\n\r\n<body>" of length n; returns the new length. Idempotent 1779// (skips if Content-Length already present, e.g. of_serve downloads) and fail-safe (no room -> unchanged). 1780func of_cl_frame(out: *u8, n: i64, cap: i64) -> i64 { 1781 if n <= 0 { return n } 1782 var p: i64 = 0 - 1 1783 var i: i64 = 0 1784 while i + 3 < n { if out[i] == (13 as u8) { if out[i+1] == (10 as u8) { if out[i+2] == (13 as u8) { if out[i+3] == (10 as u8) { p = i; i = n } } } } i = i + 1 } 1785 if p < 0 { return n } 1786 if of_memhas(out, p, "Content-Length:" as *u8) == 1 { return n } 1787 let bodylen: i64 = n - (p + 4) 1788 let ins: *u8 = sys_mmap(48) 1789 var io: i64 = of_cat(ins, 0, "Content-Length: " as *u8) 1790 io = of_catn(ins, io, bodylen) 1791 io = of_catc(ins, io, 13); io = of_catc(ins, io, 10) 1792 if n + io >= cap { return n } 1793 var s: i64 = n - 1 1794 while s >= p + 2 { out[s + io] = out[s]; s = s - 1 } 1795 var k: i64 = 0 1796 while k < io { out[p + 2 + k] = ins[k]; k = k + 1 } 1797 return n + io 1798} 1799// serve <root>/<name>/v<N>/{file.<ext>|preview.html}. mode 0 = artifact download, 1 = preview html. 1800func of_serve(root: *u8, name: *u8, vn: i64, mode: i64, out: *u8, cap: i64) -> i64 { 1801 let kb: *u8 = sys_mmap(64) 1802 let vc: i64 = of_manifest_count(root, name, kb, 64) 1803 if vc <= 0 { return 0 - 1 } 1804 if vn < 1 { return 0 - 1 } 1805 if vn > vc { return 0 - 1 } 1806 let ki: i64 = of_kind_idx(kb) 1807 var ks: i64 = ki 1808 if ks < 0 { ks = 0 } 1809 let vd: *u8 = sys_mmap(512) 1810 of_vdir(root, name, vn, vd) 1811 let fp: *u8 = sys_mmap(600) 1812 var fo: i64 = of_cat(fp, 0, vd) 1813 if mode == 1 { fo = of_cat(fp, fo, "/preview.html" as *u8) } else { fo = of_cat(fp, fo, "/file." as *u8); fo = of_cat(fp, fo, of_ext(ks)) } 1814 fp[fo] = 0 as u8 1815 let fb: *u8 = sys_mmap(1048576) 1816 let fl: i64 = of_read_file(fp, fb, 1048576) 1817 if fl < 0 { return 0 - 1 } 1818 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: " as *u8) 1819 if mode == 1 { o = of_cat(out, o, "text/html; charset=utf-8" as *u8) } else { o = of_cat(out, o, of_ct(ks)) } 1820 o = of_cat(out, o, "\r\nContent-Length: " as *u8) 1821 o = of_catn(out, o, fl) 1822 if mode == 0 { 1823 o = of_cat(out, o, "\r\nContent-Disposition: attachment; filename=" as *u8) 1824 o = of_cat(out, o, name) 1825 o = of_cat(out, o, "." as *u8) 1826 o = of_cat(out, o, of_ext(ks)) 1827 } 1828 o = of_cat(out, o, "\r\n\r\n" as *u8) 1829 var i: i64 = 0 1830 while i < fl { if o + i < cap { out[o + i] = fb[i] } i = i + 1 } 1831 return o + fl 1832} 1833// parse "/<pfx>/<name>/v<N>" -> name + N. returns N (>=1) or -1. 1834func of_parse_nv(path: *u8, pfxlen: i64, name: *u8, ncap: i64) -> i64 { 1835 var i: i64 = pfxlen 1836 var t: i64 = 0 1837 while path[i] != (0 as u8) { if path[i] == (47 as u8) { break } if t < ncap - 1 { name[t] = path[i]; t = t + 1 } i = i + 1 } 1838 name[t] = 0 as u8 1839 if t == 0 { return 0 - 1 } 1840 if path[i] != (47 as u8) { return 0 - 1 } 1841 i = i + 1 1842 if path[i] != (118 as u8) { return 0 - 1 } 1843 i = i + 1 1844 var v: i64 = 0 1845 var d: i64 = 0 1846 while path[i] != (0 as u8) { 1847 let c: i64 = path[i] as i64 1848 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); d = d + 1; i = i + 1 } else { return 0 - 1 } } else { return 0 - 1 } 1849 } 1850 if d == 0 { return 0 - 1 } 1851 return v 1852} 1853 1854// the app: request bytes -> response bytes. returns response length. 1855// base = the URL mount prefix (e.g. "/office" when reverse-proxied at nishifamily.com/office, "" for the raw 1856// daemon). The edge forwards the FULL path verbatim, so we STRIP base off the incoming path before routing while 1857// build "doc:<name>" / "user:<handle>" refs for the ReBAC plane. 1858func of_docref(out: *u8, name: *u8) -> i64 { var o: i64 = of_cat(out, 0, "doc:" as *u8); o = of_cat(out, o, name); out[o] = 0 as u8; return o } 1859func of_meref(out: *u8, handle: *u8) -> i64 { var o: i64 = of_cat(out, 0, "user:" as *u8); o = of_cat(out, o, handle); out[o] = 0 as u8; return o } 1860func of_grpref(out: *u8, gname: *u8) -> i64 { var o: i64 = of_cat(out, 0, "group:" as *u8); o = of_cat(out, o, gname); out[o] = 0 as u8; return o } 1861// the userset "group:<g>#member" -- sharing a doc with THIS grants every member of the group (Zanzibar userset). 1862func of_grpmemberref(out: *u8, gname: *u8) -> i64 { var o: i64 = of_grpref(out, gname); o = of_cat(out, o, "#member" as *u8); out[o] = 0 as u8; return o } 1863// a share target handle must be [a-zA-Z0-9_-] 1..64 -- so ':' or '#' can never forge a type/userset in a tuple ref. 1864func of_tok_ok(s: *u8) -> i64 { 1865 if s[0] == (0 as u8) { return 0 } 1866 var i: i64 = 0 1867 while s[i] != (0 as u8) { 1868 let c: i64 = s[i] as i64 1869 var ok: i64 = 0 1870 if c >= 97 { if c <= 122 { ok = 1 } } 1871 if c >= 65 { if c <= 90 { ok = 1 } } 1872 if c >= 48 { if c <= 57 { ok = 1 } } 1873 if c == 95 { ok = 1 } 1874 if c == 45 { ok = 1 } 1875 if ok == 0 { return 0 } 1876 if i >= 64 { return 0 } 1877 i = i + 1 1878 } 1879 return 1 1880} 1881func of_sess_field(dst: *u8, off: i64, tok: *u8) -> i64 { 1882 var o: i64 = off 1883 if tok[0] != (0 as u8) { o = of_cat(dst, o, "<input type='hidden' name='sess' value='" as *u8); o = of_cat(dst, o, tok); o = of_cat(dst, o, "'>" as *u8) } 1884 return o 1885} 1886// authz refusal (fail-closed: owned doc, caller not allowed). 1887func of_deny_read(out: *u8) -> i64 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 1888func of_deny_write(out: *u8) -> i64 { return of_err(out, "403 Forbidden" as *u8, "this document is owned; you need edit access (ask the owner to share it)" as *u8) } 1889func of_after_colon(s: *u8) -> *u8 { var i: i64 = 0; while s[i] != (0 as u8) { if (s[i] as i64) == 58 { return (s as i64 + i + 1) as *u8 } i = i + 1 } return s } 1890// TENANT ISOLATION OF THE GROUP PLANE (2026-08-19, LP3 -- one binary, N realm-bound instances): the nishifamily 1891// instance (the default authz prefix) keeps resolving group membership through the cross-surface relate plane exactly 1892// as before; ANY OTHER instance (a firm with its own authz prefix and its own realm of handles) resolves membership 1893// ONLY from its own plane, so a nishifamily group name can never grant a firm document and a handle that happens to 1894// be spelled the same in two realms never crosses them. Derived from the prefix, never a second configuration knob. 1895func of_relate_pfx(azprefix: *u8) -> *u8 { 1896 if of_seq(azprefix, OF_AUTHZ) == 1 { return OF_RELATE } 1897 return azprefix 1898} 1899// read/write authorization for a doc by name. UNOWNED = PUBLIC (1). OWNED = the caller needs the relation. 1900func of_read_ok(azprefix: *u8, me: *u8, authed: i64, nm: *u8) -> i64 { 1901 let dref: *u8 = sys_mmap(320); of_docref(dref, nm) 1902 if rb_obj_has_owner(azprefix, dref) == 0 { return 1 } 1903 if authed == 0 { return 0 } 1904 return rb_check2(azprefix, of_relate_pfx(azprefix), me, "read" as *u8, dref, 0) 1905} 1906func of_write_ok(azprefix: *u8, me: *u8, authed: i64, nm: *u8) -> i64 { 1907 let dref: *u8 = sys_mmap(320); of_docref(dref, nm) 1908 if rb_obj_has_owner(azprefix, dref) == 0 { return 1 } 1909 if authed == 0 { return 0 } 1910 return rb_check2(azprefix, of_relate_pfx(azprefix), me, "write" as *u8, dref, 0) 1911} 1912// SHARE(grant=1)/UNSHARE(grant=0) an OWNED doc -- owner-only. doc:<name> viewer|editor user:<who>. 1913func of_do_share(base: *u8, azprefix: *u8, me: *u8, handle: *u8, authed: i64, body: *u8, blen: i64, out: *u8, grant: i64) -> i64 { 1914 if authed == 0 { return of_deny_write(out) } 1915 let nm: *u8 = sys_mmap(64); let who: *u8 = sys_mmap(64); let lv: *u8 = sys_mmap(16) 1916 of_form_get(body, blen, "name" as *u8, nm, 64) 1917 of_form_get(body, blen, "who" as *u8, who, 64) 1918 of_form_get(body, blen, "level" as *u8, lv, 16) 1919 if of_name_ok(nm) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 1920 if of_tok_ok(who) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad handle" as *u8) } 1921 let dref: *u8 = sys_mmap(320); of_docref(dref, nm) 1922 if rb_obj_has_owner(azprefix, dref) == 0 { return of_err(out, "400 Bad Request" as *u8, "save the document first (it becomes yours), then share it" as *u8) } 1923 if rb_check(azprefix, me, "manage" as *u8, dref, 0) == 0 { return of_deny_write(out) } 1924 var rel: *u8 = "viewer" as *u8 1925 if of_seq(lv, "editor" as *u8) == 1 { rel = "editor" as *u8 } 1926 // target=group -> share with the userset group:<who>#member (every group member gets access); else a person. 1927 let tgt: *u8 = sys_mmap(16); of_form_get(body, blen, "target" as *u8, tgt, 16) 1928 let wref: *u8 = sys_mmap(320) 1929 if of_seq(tgt, "group" as *u8) == 1 { of_grpmemberref(wref, who) } else { of_meref(wref, who) } 1930 rb_put(azprefix, dref, rel, wref, handle, grant) 1931 var o: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 1932 o = of_cat(out, o, base); o = of_cat(out, o, "/manage/" as *u8); o = of_cat(out, o, nm); o = of_cat(out, o, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 1933 return o 1934} 1935// copy s into dst up to a '#' (or end), NUL-term. "elders#member" -> "elders". 1936func of_before_hash(dst: *u8, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { if (s[i] as i64) == 35 { dst[i] = 0 as u8; return i } dst[i] = s[i]; i = i + 1 } dst[i] = 0 as u8; return i } 1937// render one shared-with row + its unshare button. subref = "user:<h>" (a person) OR "group:<g>#member" (a group). 1938func of_share_row(out: *u8, off: i64, base: *u8, nm: *u8, subref: *u8, rel: *u8, tok: *u8) -> i64 { 1939 var target: *u8 = "user" as *u8 1940 let who: *u8 = sys_mmap(96) 1941 let label: *u8 = sys_mmap(128) 1942 if of_starts(subref, "group:" as *u8) == 1 { 1943 target = "group" as *u8 1944 of_before_hash(who, of_after_colon(subref)) 1945 var lo: i64 = of_cat(label, 0, "group " as *u8); lo = of_cat(label, lo, who); label[lo] = 0 as u8 1946 } else { 1947 var wo: i64 = of_cat(who, 0, of_after_colon(subref)); who[wo] = 0 as u8 1948 var lo: i64 = of_cat(label, 0, who); label[lo] = 0 as u8 1949 } 1950 var o: i64 = of_cat(out, off, "<div class='row'>" as *u8) 1951 o = of_cat(out, o, label); o = of_cat(out, o, " <span class='mut'>" as *u8); o = of_cat(out, o, rel) 1952 o = of_cat(out, o, "</span> <form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/unshare' style='display:inline'>" as *u8) 1953 o = of_sess_field(out, o, tok) 1954 o = of_cat(out, o, "<input type='hidden' name='name' value='" as *u8); o = of_cat(out, o, nm) 1955 o = of_cat(out, o, "'><input type='hidden' name='who' value='" as *u8); o = of_cat(out, o, who) 1956 o = of_cat(out, o, "'><input type='hidden' name='target' value='" as *u8); o = of_cat(out, o, target) 1957 o = of_cat(out, o, "'><input type='hidden' name='level' value='" as *u8); o = of_cat(out, o, rel) 1958 o = of_cat(out, o, "'><button class='ghost'>unshare</button></form></div>" as *u8) 1959 return o 1960} 1961// the owner's Sharing panel for a doc. returns inner-HTML length, or negative (=-1 unauth / -2 not-owned / -3 not-owner). 1962func of_managepage(base: *u8, azprefix: *u8, me: *u8, authed: i64, nm: *u8, tok: *u8, out: *u8, cap: i64) -> i64 { 1963 let dref: *u8 = sys_mmap(320); of_docref(dref, nm) 1964 if authed == 0 { return 0 - 1 } 1965 if rb_obj_has_owner(azprefix, dref) == 0 { return 0 - 2 } 1966 if rb_check(azprefix, me, "manage" as *u8, dref, 0) == 0 { return 0 - 3 } 1967 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>Sharing</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:720px;margin:5vh auto;padding:0 20px;color:#222}.row{padding:8px 0;border-bottom:1px solid #e5e7eb}.mut{color:#888}button{border:0;border-radius:8px;padding:8px 12px;background:rgb(41,84,164);color:#fff;font-weight:600}.ghost{background:#eee;color:#333;padding:4px 10px}input,select{padding:7px;border:1px solid #ccc;border-radius:8px;margin-right:6px}</style></head><body><div class='wrap'><h2>Sharing: " as *u8); o = of_cat(out, o, nm); o = of_cat(out, o, "</h2>" as *u8) 1968 o = of_cat(out, o, "<p class='mut'>You own this document. Share it with a person by handle as viewer or editor; unshare revokes.</p><h3>Shared with</h3>" as *u8) 1969 let vv: *i64 = sys_mmap(8 * 64) as *i64 1970 let nv: i64 = rb_list_subjects(azprefix, dref, "viewer" as *u8, vv, 64) 1971 let ee: *i64 = sys_mmap(8 * 64) as *i64 1972 let ne: i64 = rb_list_subjects(azprefix, dref, "editor" as *u8, ee, 64) 1973 if nv == 0 { if ne == 0 { o = of_cat(out, o, "<div class='mut'>(not shared with anyone yet)</div>" as *u8) } } 1974 var qi: i64 = 0 1975 while qi < ne { o = of_share_row(out, o, base, nm, ee[qi] as *u8, "editor" as *u8, tok); qi = qi + 1 } 1976 qi = 0 1977 while qi < nv { o = of_share_row(out, o, base, nm, vv[qi] as *u8, "viewer" as *u8, tok); qi = qi + 1 } 1978 o = of_cat(out, o, "<h3>Share with someone</h3><form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/share'>" as *u8) 1979 o = of_sess_field(out, o, tok) 1980 o = of_cat(out, o, "<input type='hidden' name='name' value='" as *u8); o = of_cat(out, o, nm) 1981 o = of_cat(out, o, "'><input name='who' placeholder='person handle or group name'> <select name='target'><option value='user'>person</option><option value='group'>group</option></select> <select name='level'><option>viewer</option><option>editor</option></select> <button>Share</button></form>" as *u8) 1982 o = of_cat(out, o, "<p class='mut'>Share with a <a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/groups'>group</a> and every member gets access.</p>" as *u8) 1983 o = of_cat(out, o, "<p><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/doc/" as *u8); o = of_cat(out, o, nm); o = of_cat(out, o, "'>&larr; back to document</a></p></div></body></html>" as *u8) 1984 return o 1985} 1986 1987// GROUP membership handler: add(1)/remove(0) a member. The caller bootstraps/owns the group. 303 -> /groups. 1988func of_do_group(base: *u8, azprefix: *u8, me: *u8, handle: *u8, authed: i64, body: *u8, blen: i64, out: *u8, add: i64) -> i64 { 1989 if authed == 0 { return of_deny_write(out) } 1990 let gn: *u8 = sys_mmap(64); let who: *u8 = sys_mmap(64) 1991 of_form_get(body, blen, "group" as *u8, gn, 64) 1992 of_form_get(body, blen, "who" as *u8, who, 64) 1993 if of_tok_ok(gn) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad group name" as *u8) } 1994 if of_tok_ok(who) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad handle" as *u8) } 1995 let gref: *u8 = sys_mmap(320); of_grpref(gref, gn) 1996 if rb_may_grant(azprefix, me, gref) == 0 { return of_deny_write(out) } 1997 if rb_obj_has_owner(azprefix, gref) == 0 { 1998 rb_put(azprefix, gref, "owner" as *u8, me, handle, 1) 1999 rb_put(azprefix, gref, "member" as *u8, me, handle, 1) 2000 } 2001 let wref: *u8 = sys_mmap(320); of_meref(wref, who) 2002 rb_put(azprefix, gref, "member" as *u8, wref, handle, add) 2003 var o: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2004 o = of_cat(out, o, base); o = of_cat(out, o, "/groups\r\n\r\n" as *u8) 2005 return o 2006} 2007// the caller's GROUPS page (owned groups + members + management forms). returns a FULL HTTP response. 2008func of_groupspage(base: *u8, azprefix: *u8, me: *u8, authed: i64, tok: *u8, out: *u8, cap: i64) -> i64 { 2009 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>My groups</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:720px;margin:5vh auto;padding:0 20px;color:#222}.row{padding:6px 0;border-bottom:1px solid #eee}.mut{color:#888}button{border:0;border-radius:8px;padding:8px 12px;background:rgb(41,84,164);color:#fff;font-weight:600}.ghost{background:#eee;color:#333;padding:3px 9px}input{padding:7px;border:1px solid #ccc;border-radius:8px;margin-right:6px}</style></head><body><h2>My groups</h2>" as *u8) 2010 if authed == 0 { o = of_cat(out, o, "<p>Sign in to manage groups.</p></body></html>" as *u8); return o } 2011 o = of_cat(out, o, "<p class='mut'>Groups you own. Add people by handle; share a document with a group and every member gets access (revoke a member and they lose it everywhere).</p>" as *u8) 2012 let gg: *i64 = sys_mmap(8 * 64) as *i64 2013 let ng: i64 = rb_list_objects_for_sub(azprefix, me, "owner" as *u8, gg, 64) 2014 if ng == 0 { o = of_cat(out, o, "<div class='mut'>(no groups yet -- create one below)</div>" as *u8) } 2015 var gi: i64 = 0 2016 while gi < ng { 2017 let gref: *u8 = gg[gi] as *u8 2018 let gbare: *u8 = of_after_colon(gref) 2019 o = of_cat(out, o, "<h3>" as *u8); o = of_cat(out, o, gbare); o = of_cat(out, o, "</h3>" as *u8) 2020 let mm: *i64 = sys_mmap(8 * 64) as *i64 2021 let nm2: i64 = rb_list_subjects(azprefix, gref, "member" as *u8, mm, 64) 2022 var mi: i64 = 0 2023 while mi < nm2 { 2024 let mbare: *u8 = of_after_colon(mm[mi] as *u8) 2025 o = of_cat(out, o, "<div class='row'>" as *u8); o = of_cat(out, o, mbare) 2026 o = of_cat(out, o, " <form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/group-remove' style='display:inline'>" as *u8) 2027 o = of_sess_field(out, o, tok) 2028 o = of_cat(out, o, "<input type='hidden' name='group' value='" as *u8); o = of_cat(out, o, gbare) 2029 o = of_cat(out, o, "'><input type='hidden' name='who' value='" as *u8); o = of_cat(out, o, mbare) 2030 o = of_cat(out, o, "'><button class='ghost'>remove</button></form></div>" as *u8) 2031 mi = mi + 1 2032 } 2033 o = of_cat(out, o, "<form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/group-add'>" as *u8) 2034 o = of_sess_field(out, o, tok) 2035 o = of_cat(out, o, "<input type='hidden' name='group' value='" as *u8); o = of_cat(out, o, gbare) 2036 o = of_cat(out, o, "'><input name='who' placeholder='handle to add'><button>Add member</button></form>" as *u8) 2037 gi = gi + 1 2038 } 2039 o = of_cat(out, o, "<h3>Create a group</h3><form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/group-add'>" as *u8) 2040 o = of_sess_field(out, o, tok) 2041 o = of_cat(out, o, "<input name='group' placeholder='new group name'><input name='who' placeholder='first member handle'><button>Create</button></form>" as *u8) 2042 o = of_cat(out, o, "<p><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/'>&larr; back to office</a></p></body></html>" as *u8) 2043 return o 2044} 2045 2046// REVERSE INDEX: append the doc: objects where (obj, rel, sub) is current into out[] (deduped). returns new count. 2047func of_collect_docs(azprefix: *u8, sub: *u8, rel: *u8, out: *i64, n: i64, cap: i64) -> i64 { 2048 let tmp: *i64 = sys_mmap(8 * 64) as *i64 2049 let k: i64 = rb_list_objects_for_sub(azprefix, sub, rel, tmp, 64) 2050 var i: i64 = 0; var nn: i64 = n 2051 while i < k { 2052 let o: *u8 = tmp[i] as *u8 2053 if of_starts(o, "doc:" as *u8) == 1 { if nn < cap { if rb_in_list(out, nn, o) == 0 { out[nn] = o as i64; nn = nn + 1 } } } 2054 i = i + 1 2055 } 2056 return nn 2057} 2058// "what documents can I access?" -- the reverse-index query: docs I own/view/edit DIRECTLY, plus docs shared with 2059// any GROUP I'm a member of (userset expansion on the read side). Deduped. This is the SOTA list-objects primitive. 2060func of_my_docs(azprefix: *u8, me: *u8, out: *i64, cap: i64) -> i64 { 2061 var n: i64 = 0 2062 n = of_collect_docs(azprefix, me, "owner" as *u8, out, n, cap) 2063 n = of_collect_docs(azprefix, me, "viewer" as *u8, out, n, cap) 2064 n = of_collect_docs(azprefix, me, "editor" as *u8, out, n, cap) 2065 let grps: *i64 = sys_mmap(8 * 64) as *i64 2066 let ng: i64 = rb_list_objects_for_sub(azprefix, me, "member" as *u8, grps, 64) 2067 var gi: i64 = 0 2068 while gi < ng { 2069 let g: *u8 = grps[gi] as *u8 2070 if of_starts(g, "group:" as *u8) == 1 { 2071 let gm: *u8 = sys_mmap(320); var go: i64 = of_cat(gm, 0, g); go = of_cat(gm, go, "#member" as *u8); gm[go] = 0 as u8 2072 n = of_collect_docs(azprefix, gm, "viewer" as *u8, out, n, cap) 2073 n = of_collect_docs(azprefix, gm, "editor" as *u8, out, n, cap) 2074 } 2075 gi = gi + 1 2076 } 2077 return n 2078} 2079// the "Shared with me" page: every doc the caller can reach (direct or via a group). FULL HTTP response. 2080func of_sharedpage(base: *u8, azprefix: *u8, me: *u8, authed: i64, out: *u8, cap: i64) -> i64 { 2081 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>Shared with me</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:720px;margin:5vh auto;padding:0 20px;color:#222}.row{padding:8px 0;border-bottom:1px solid #eee}.mut{color:#888}a{color:rgb(41,84,164)}</style></head><body><h2>Documents you can access</h2>" as *u8) 2082 if authed == 0 { o = of_cat(out, o, "<p>Sign in to see documents shared with you.</p></body></html>" as *u8); return o } 2083 let docs: *i64 = sys_mmap(8 * 128) as *i64 2084 let nd: i64 = of_my_docs(azprefix, me, docs, 128) 2085 o = of_cat(out, o, "<p class='mut'>Owned by you, shared with you directly, or shared with a group you belong to.</p>" as *u8) 2086 if nd == 0 { o = of_cat(out, o, "<div class='mut'>(nothing yet)</div>" as *u8) } 2087 var di: i64 = 0 2088 while di < nd { 2089 let dbare: *u8 = of_after_colon(docs[di] as *u8) 2090 o = of_cat(out, o, "<div class='row'><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/doc/" as *u8); o = of_cat(out, o, dbare); o = of_cat(out, o, "'>" as *u8); o = of_cat(out, o, dbare); o = of_cat(out, o, "</a></div>" as *u8) 2091 di = di + 1 2092 } 2093 o = of_cat(out, o, "<p><a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/'>&larr; back to office</a></p></body></html>" as *u8) 2094 return o 2095} 2096 2097// generated links KEEP base -> the app is mount-point agnostic (works at :8030/ and at nishifamily.com/office/). 2098// ==== LP1 IMPORT + LP4 SIGN + firm-instance helpers (2026-08-19, /compare/legalpractice 0.1) ============================= 2099// Every constant below is NAMED for one purpose; sizes that depend on the input are derived from it, never guessed. 2100const OF_IMPORT_MAXPARTS: i64 = 8 // an import form carries file + name (+ sess); 8 is the parser slot count, refused above 2101const OF_SPEC_CAP: i64 = 131072 // the spec ceiling of_save already enforces (sl > 131072 is refused there too) 2102const OF_CAPTURE_CAP: i64 = 262144 // capture of the format organ's spec dump = spec cap + marker lines + slack 2103const OF_HEADSZ: i64 = 32 // sha256 audit head (se_chain out32) 2104const OF_HEXSZ: i64 = 64 // its hex form 2105const OF_EID_CAP: i64 = 128 // "<name>-v<N>" envelope id 2106const OF_CERT_CAP: i64 = 2048 // canon_encode of the 5-key completion certificate 2107const OF_USEC_PER_SEC: i64 = 1000000 2108const OF_NAME_MAX: i64 = 40 // of_name_ok's own limit (a-z 0-9 dash, max 40) 2109const OF_IMPORT_DOCX: i64 = 1 2110const OF_IMPORT_ODT: i64 = 2 2111const OF_ODT_ELF: *u8 = "_offc/nx_odt.elf" 2112 2113// Content-Type boundary token of a multipart request (0 = absent). Quotes stripped, stops at ';'. 2114func of_ct_boundary(req: *u8, reqlen: i64, out: *u8, cap: i64) -> i64 { 2115 let ct: *u8 = sys_mmap(512) 2116 of_hdr_get(req, reqlen, "Content-Type:" as *u8, ct, 512) 2117 var i: i64 = 0 2118 var bs: i64 = 0 - 1 2119 while ct[i] != (0 as u8) { if bs < 0 { if of_starts((ct as i64 + i) as *u8, "boundary=" as *u8) == 1 { bs = i + 9 } } i = i + 1 } 2120 if bs < 0 { out[0] = 0 as u8; return 0 } 2121 var w: i64 = 0 2122 var k: i64 = bs 2123 while ct[k] != (0 as u8) { let c: i64 = ct[k] as i64; if c == 59 { break } if c != 34 { if w < cap - 1 { out[w] = ct[k]; w = w + 1 } } k = k + 1 } 2124 out[w] = 0 as u8 2125 return w 2126} 2127// a quoted value (key like name=" or filename=") out of one part's header block; 0 = absent 2128func of_cd_extract(body: *u8, hoff: i64, hlen: i64, key: *u8, out: *u8, cap: i64) -> i64 { 2129 let kl: i64 = of_slen(key) 2130 let end: i64 = hoff + hlen 2131 var i: i64 = hoff 2132 var start: i64 = 0 - 1 2133 while i + kl <= end { if start < 0 { var m: i64 = 1; var j: i64 = 0; while j < kl { if body[i + j] != key[j] { m = 0; j = kl } else { j = j + 1 } } if m == 1 { start = i + kl } } i = i + 1 } 2134 if start < 0 { out[0] = 0 as u8; return 0 } 2135 var w: i64 = 0 2136 var k: i64 = start 2137 while k < end { if (body[k] as i64) == 34 { k = end } else { if w < cap - 1 { out[w] = body[k]; w = w + 1 } k = k + 1 } } 2138 out[w] = 0 as u8 2139 return w 2140} 2141// an office name from an uploaded filename: drop the extension (last '.'), lowercase, keep a-z 0-9 dash, space/_ -> dash 2142func of_name_from_filename(fn: *u8, out: *u8) -> i64 { 2143 var last: i64 = 0 - 1 2144 var i: i64 = 0 2145 while fn[i] != (0 as u8) { if (fn[i] as i64) == 46 { last = i } i = i + 1 } 2146 var stop: i64 = i 2147 if last > 0 { stop = last } 2148 var o: i64 = 0 2149 i = 0 2150 while i < stop { 2151 var c: i64 = fn[i] as i64 2152 if c >= 65 { if c <= 90 { c = c + 32 } } 2153 var keep: i64 = 0 2154 if c >= 97 { if c <= 122 { keep = 1 } } 2155 if c >= 48 { if c <= 57 { keep = 1 } } 2156 if c == 45 { keep = 1 } 2157 if c == 32 { c = 45; keep = 1 } 2158 if c == 95 { c = 45; keep = 1 } 2159 if keep == 1 { if o < OF_NAME_MAX { out[o] = c as u8; o = o + 1 } } 2160 i = i + 1 2161 } 2162 out[o] = 0 as u8 2163 return o 2164} 2165// what was uploaded: OF_IMPORT_DOCX / OF_IMPORT_ODT by extension, and ONLY if the bytes are a ZIP package (PK\3\4) 2166func of_import_kind(fn: *u8, bytes: *u8, n: i64) -> i64 { 2167 if n < 4 { return 0 } 2168 if bytes[0] != (80 as u8) { return 0 } 2169 if bytes[1] != (75 as u8) { return 0 } 2170 if bytes[2] != (3 as u8) { return 0 } 2171 if bytes[3] != (4 as u8) { return 0 } 2172 let l: i64 = of_slen(fn) 2173 let low: *u8 = sys_mmap(l + 1) 2174 var i: i64 = 0 2175 while i < l { var c: i64 = fn[i] as i64; if c >= 65 { if c <= 90 { c = c + 32 } } low[i] = c as u8; i = i + 1 } 2176 low[l] = 0 as u8 2177 if l >= 5 { if of_seq((low as i64 + l - 5) as *u8, ".docx" as *u8) == 1 { return OF_IMPORT_DOCX } } 2178 if l >= 4 { if of_seq((low as i64 + l - 4) as *u8, ".odt" as *u8) == 1 { return OF_IMPORT_ODT } } 2179 return 0 2180} 2181// IMPORT (LP1): an uploaded .docx/.odt lands as v1 of a NEW document. The ORIGINAL bytes are kept byte for byte 2182// (v1/original.<ext>; for .docx v1/file.docx IS the original, so /file serves it untouched until the first edit); 2183// the spec is extracted PARAGRAPH-FAITHFULLY by the format organ's `spec` verb (H/P/T lines), the preview is 2184// rendered by the same organ, and the manifest row carries the additive 4th field "import". Returns 1, or LOUD: 2185// -1 bad name -2 name exists (import never appends to a document) -3 not a .docx/.odt package -4 extract failed 2186// -5 convert/preview/write failed -6 nothing readable in the document 2187func of_import(root: *u8, base: *u8, name: *u8, fn: *u8, bytes: *u8, n: i64) -> i64 { 2188 if of_name_ok(name) == 0 { return 0 - 1 } 2189 sys_mkdir(root, 493) 2190 let lk: i64 = of_doc_lock(root, name) 2191 let rc: i64 = of_import_body(root, base, name, fn, bytes, n) 2192 of_doc_unlock(lk) 2193 return rc 2194} 2195func of_import_body(root: *u8, base: *u8, name: *u8, fn: *u8, bytes: *u8, n: i64) -> i64 { 2196 if of_name_ok(name) == 0 { return 0 - 1 } 2197 let kbuf: *u8 = sys_mmap(64) 2198 if of_manifest_count(root, name, kbuf, 64) > 0 { return 0 - 2 } 2199 let ik: i64 = of_import_kind(fn, bytes, n) 2200 if ik == 0 { return 0 - 3 } 2201 sys_mkdir(root, 493) 2202 let nd: *u8 = sys_mmap(512) 2203 var no: i64 = of_cat(nd, 0, root); no = of_cat(nd, no, "/" as *u8); no = of_cat(nd, no, name); nd[no] = 0 as u8 2204 sys_mkdir(nd, 493) 2205 let vd: *u8 = sys_mmap(512) 2206 of_vdir(root, name, 1, vd) 2207 sys_mkdir(vd, 493) 2208 let origp: *u8 = sys_mmap(600) 2209 var oo: i64 = of_cat(origp, 0, vd); oo = of_cat(origp, oo, "/original." as *u8) 2210 if ik == OF_IMPORT_DOCX { oo = of_cat(origp, oo, "docx" as *u8) } else { oo = of_cat(origp, oo, "odt" as *u8) } 2211 origp[oo] = 0 as u8 2212 if of_write_file(origp, bytes, n) != 0 { return 0 - 5 } 2213 let elf: *u8 = of_elf(0) 2214 var xelf: *u8 = elf 2215 if ik == OF_IMPORT_ODT { xelf = OF_ODT_ELF } 2216 let av: *i64 = sys_mmap(8 * 8) as *i64 2217 av[0] = xelf as i64; av[1] = "spec" as *u8 as i64; av[2] = origp as i64; av[3] = 0 2218 let capbuf: *u8 = sys_mmap(OF_CAPTURE_CAP) 2219 let ol: *i64 = sys_mmap(16) as *i64 2220 let rc: i64 = tr_run_capture(xelf, av, capbuf, OF_CAPTURE_CAP, ol) 2221 if rc != 0 { return 0 - 4 } 2222 let bpos: i64 = of_findpos(capbuf, ol[0], "-SPEC-BEGIN\n" as *u8) 2223 if bpos < 0 { return 0 - 4 } 2224 let s: i64 = bpos + 12 2225 let epos: i64 = of_findpos(capbuf, ol[0], "-SPEC-END len=" as *u8) 2226 if epos < s { return 0 - 4 } 2227 var e: i64 = epos 2228 while e > s { if capbuf[e - 1] == (10 as u8) { break } e = e - 1 } 2229 let sl: i64 = e - s 2230 if sl <= 0 { return 0 - 6 } 2231 if sl > OF_SPEC_CAP { return 0 - 4 } 2232 let spec: *u8 = sys_mmap(sl + 1) 2233 var q: i64 = 0 2234 while q < sl { spec[q] = capbuf[s + q]; q = q + 1 } 2235 spec[sl] = 0 as u8 2236 let specp: *u8 = sys_mmap(600) 2237 var so: i64 = of_cat(specp, 0, vd); so = of_cat(specp, so, "/spec.txt" as *u8); specp[so] = 0 as u8 2238 if of_write_file(specp, spec, sl) != 0 { return 0 - 5 } 2239 let artp: *u8 = sys_mmap(600) 2240 var ao: i64 = of_cat(artp, 0, vd); ao = of_cat(artp, ao, "/file.docx" as *u8); artp[ao] = 0 as u8 2241 if ik == OF_IMPORT_DOCX { if of_write_file(artp, bytes, n) != 0 { return 0 - 5 } } else { 2242 let av1: *i64 = sys_mmap(8 * 8) as *i64 2243 av1[0] = elf as i64; av1[1] = "writerich" as *u8 as i64; av1[2] = artp as i64; av1[3] = specp as i64; av1[4] = 0 2244 let rc1: i64 = tr_run_capture(elf, av1, capbuf, OF_CAPTURE_CAP, ol) 2245 if rc1 != 0 { return 0 - 5 } 2246 } 2247 let prevp: *u8 = sys_mmap(600) 2248 var po: i64 = of_cat(prevp, 0, vd); po = of_cat(prevp, po, "/preview.html" as *u8); prevp[po] = 0 as u8 2249 let dlu: *u8 = sys_mmap(600) 2250 var du: i64 = of_cat(dlu, 0, base); du = of_cat(dlu, du, "/file/" as *u8); du = of_cat(dlu, du, name); du = of_cat(dlu, du, "/v1" as *u8); dlu[du] = 0 as u8 2251 let av2: *i64 = sys_mmap(8 * 8) as *i64 2252 av2[0] = elf as i64; av2[1] = "html" as *u8 as i64; av2[2] = artp as i64; av2[3] = prevp as i64; av2[4] = dlu as i64; av2[5] = 0 2253 let rc2: i64 = tr_run_capture(elf, av2, capbuf, OF_CAPTURE_CAP, ol) 2254 if rc2 != 0 { return 0 - 5 } 2255 let mp: *u8 = sys_mmap(600) 2256 var mo: i64 = of_cat(mp, 0, nd); mo = of_cat(mp, mo, "/manifest.txt" as *u8); mp[mo] = 0 as u8 2257 let line: *u8 = sys_mmap(256) 2258 var lo: i64 = of_cat(line, 0, "v1" as *u8); lo = of_catc(line, lo, 9); lo = of_cat(line, lo, "doc" as *u8); lo = of_catc(line, lo, 9); lo = of_catn(line, lo, sys_now_us()); lo = of_catc(line, lo, 9); lo = of_cat(line, lo, "import" as *u8); lo = of_catc(line, lo, 10) 2259 if of_append_line(mp, line, lo) != 0 { return 0 - 5 } 2260 let ip: *u8 = sys_mmap(600) 2261 var io: i64 = of_cat(ip, 0, root); io = of_cat(ip, io, "/index.txt" as *u8); ip[io] = 0 as u8 2262 let il: *u8 = sys_mmap(256) 2263 var ilo: i64 = of_cat(il, 0, name); ilo = of_catc(il, ilo, 9); ilo = of_cat(il, ilo, "doc" as *u8); ilo = of_catc(il, ilo, 10) 2264 of_append_line(ip, il, ilo) 2265 return 1 2266} 2267// /original/<name>/v<N>: the untouched upload (original.odt | original.docx), else the version's file.docx 2268func of_serve_original(root: *u8, name: *u8, vn: i64, out: *u8, cap: i64) -> i64 { 2269 let kb: *u8 = sys_mmap(64) 2270 let vc: i64 = of_manifest_count(root, name, kb, 64) 2271 if vc <= 0 { return 0 - 1 } 2272 if vn < 1 { return 0 - 1 } 2273 if vn > vc { return 0 - 1 } 2274 let vd: *u8 = sys_mmap(512) 2275 of_vdir(root, name, vn, vd) 2276 let pth: *u8 = sys_mmap(600) 2277 var ct: *u8 = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" as *u8 2278 var ext: *u8 = "docx" as *u8 2279 var po: i64 = of_cat(pth, 0, vd); po = of_cat(pth, po, "/original.odt" as *u8); pth[po] = 0 as u8 2280 var fd: i64 = sys_openat_rd(pth) 2281 if fd >= 0 { sys_close(fd); ct = "application/vnd.oasis.opendocument.text" as *u8; ext = "odt" as *u8 } else { 2282 po = of_cat(pth, 0, vd); po = of_cat(pth, po, "/original.docx" as *u8); pth[po] = 0 as u8 2283 fd = sys_openat_rd(pth) 2284 if fd >= 0 { sys_close(fd) } else { po = of_cat(pth, 0, vd); po = of_cat(pth, po, "/file.docx" as *u8); pth[po] = 0 as u8 } 2285 } 2286 let szp: *i64 = sys_mmap(16) as *i64 2287 let fb: *u8 = ss_readall(pth, szp) 2288 if (fb as i64) == 0 { return 0 - 1 } 2289 let fl: i64 = szp[0] 2290 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: " as *u8) 2291 o = of_cat(out, o, ct) 2292 o = of_cat(out, o, "\r\nContent-Length: " as *u8) 2293 o = of_catn(out, o, fl) 2294 o = of_cat(out, o, "\r\nContent-Disposition: attachment; filename=" as *u8) 2295 o = of_cat(out, o, name); o = of_cat(out, o, "." as *u8); o = of_cat(out, o, ext) 2296 o = of_cat(out, o, "\r\n\r\n" as *u8) 2297 if o + fl > cap { sys_munmap(fb, fl); return 0 - 2 } 2298 var i: i64 = 0 2299 while i < fl { out[o + i] = fb[i]; i = i + 1 } 2300 sys_munmap(fb, fl) 2301 return o + fl 2302} 2303// hex (64 chars) -> 32 bytes; returns 1 on a clean parse, 0 if any char is not hex 2304func of_is_hex(c: i64) -> i64 { 2305 if c >= 48 { if c <= 57 { return 1 } } 2306 if c >= 65 { if c <= 70 { return 1 } } 2307 if c >= 97 { if c <= 102 { return 1 } } 2308 return 0 2309} 2310func of_unhex32(hx: *u8, out32: *u8) -> i64 { 2311 var i: i64 = 0 2312 while i < OF_HEADSZ { 2313 let ca: i64 = hx[i * 2] as i64 2314 let cb: i64 = hx[i * 2 + 1] as i64 2315 if of_is_hex(ca) == 0 { return 0 } 2316 if of_is_hex(cb) == 0 { return 0 } 2317 out32[i] = (of_hexval(ca) * 16 + of_hexval(cb)) as u8 2318 i = i + 1 2319 } 2320 return 1 2321} 2322func of_count_lines(path: *u8) -> i64 { 2323 let szp: *i64 = sys_mmap(16) as *i64 2324 let b: *u8 = ss_readall(path, szp) 2325 if (b as i64) == 0 { return 0 } 2326 var n: i64 = 0 2327 var i: i64 = 0 2328 while i < szp[0] { if b[i] == (10 as u8) { n = n + 1 } i = i + 1 } 2329 sys_munmap(b, szp[0]) 2330 return n 2331} 2332func of_cert_exists(root: *u8, name: *u8, vn: i64) -> i64 { 2333 let vd: *u8 = sys_mmap(512) 2334 of_vdir(root, name, vn, vd) 2335 let cp: *u8 = sys_mmap(600) 2336 var co: i64 = of_cat(cp, 0, vd); co = of_cat(cp, co, "/cert.txt" as *u8); cp[co] = 0 as u8 2337 let fd: i64 = sys_openat_rd(cp) 2338 if fd < 0 { return 0 } 2339 sys_close(fd) 2340 return 1 2341} 2342// SIGN (LP4): the UETA consent-gated ceremony over a document VERSION. doc CID = cid_of the version's bytes; the 2343// envelope id is "<name>-v<N>"; every signature chains the audit head (se_genesis -> sc_sign), persisted beside the 2344// version (v<N>/sign.head hex + v<N>/sign.log append-only); the sealed certificate (sc_cert) is written to 2345// v<N>/cert.txt, put on the registry plane under root/<name>/sign- and its CID returned; the document-level ledger 2346// <name>/signatures.txt gains one row. Returns 1, or -1 no such version -2 consent refused (no intent, no 2347// signature, head untouched) -3 bad signer -4 write failed. 2348func of_sign_version(root: *u8, name: *u8, vn: i64, signer: *u8, consent: *u8, out_cert_cid: *u8) -> i64 { 2349 if of_name_ok(name) == 0 { return 0 - 1 } 2350 let lk: i64 = of_doc_lock(root, name) 2351 let rc: i64 = of_sign_version_body(root, name, vn, signer, consent, out_cert_cid) 2352 of_doc_unlock(lk) 2353 return rc 2354} 2355func of_sign_version_body(root: *u8, name: *u8, vn: i64, signer: *u8, consent: *u8, out_cert_cid: *u8) -> i64 { 2356 let kb: *u8 = sys_mmap(64) 2357 let vc: i64 = of_manifest_count(root, name, kb, 64) 2358 if vc <= 0 { return 0 - 1 } 2359 if vn < 1 { return 0 - 1 } 2360 if vn > vc { return 0 - 1 } 2361 if of_tok_ok(signer) == 0 { return 0 - 3 } 2362 if sc_consent_ok(consent) == 0 { return 0 - 2 } 2363 let ki: i64 = of_kind_idx(kb) 2364 var ks: i64 = ki 2365 if ks < 0 { ks = 0 } 2366 let vd: *u8 = sys_mmap(512) 2367 of_vdir(root, name, vn, vd) 2368 let fp: *u8 = sys_mmap(600) 2369 var fo: i64 = of_cat(fp, 0, vd); fo = of_cat(fp, fo, "/file." as *u8); fo = of_cat(fp, fo, of_ext(ks)); fp[fo] = 0 as u8 2370 let szbox: *i64 = sys_mmap(16) as *i64 2371 let doccid: *u8 = sys_mmap(128) 2372 if cid_of_file(fp, szbox, doccid) < 0 { return 0 - 1 } 2373 let eid: *u8 = sys_mmap(OF_EID_CAP) 2374 var eo: i64 = of_cat(eid, 0, name); eo = of_cat(eid, eo, "-v" as *u8); eo = of_catn(eid, eo, vn); eid[eo] = 0 as u8 2375 let headp: *u8 = sys_mmap(600) 2376 var hpo: i64 = of_cat(headp, 0, vd); hpo = of_cat(headp, hpo, "/sign.head" as *u8); headp[hpo] = 0 as u8 2377 let logp: *u8 = sys_mmap(600) 2378 var lpo: i64 = of_cat(logp, 0, vd); lpo = of_cat(logp, lpo, "/sign.log" as *u8); logp[lpo] = 0 as u8 2379 let prev: *u8 = sys_mmap(OF_HEADSZ) 2380 let hexin: *u8 = sys_mmap(OF_HEXSZ + 2) 2381 let hl: i64 = of_read_file(headp, hexin, OF_HEXSZ) 2382 var seq: i64 = 1 2383 var chained: i64 = 0 2384 if hl == OF_HEXSZ { if of_unhex32(hexin, prev) == 1 { chained = 1; seq = of_count_lines(logp) + 1 } } 2385 if chained == 0 { se_genesis(prev) } 2386 let head: *u8 = sys_mmap(OF_HEADSZ) 2387 let ts: i64 = sys_now_us() / OF_USEC_PER_SEC 2388 if sc_sign(eid, seq, signer, ts, consent, prev, head) != 1 { return 0 - 2 } 2389 let hexh: *u8 = sys_mmap(OF_HEXSZ + 2) 2390 se_hex(head, hexh) 2391 if of_write_file(headp, hexh, OF_HEXSZ) != 0 { return 0 - 4 } 2392 let row: *u8 = sys_mmap(512) 2393 var ro: i64 = of_catn(row, 0, seq); ro = of_catc(row, ro, 9); ro = of_cat(row, ro, signer); ro = of_catc(row, ro, 9); ro = of_catn(row, ro, ts); ro = of_catc(row, ro, 9) 2394 var z: i64 = 0 2395 while z < OF_HEXSZ { row[ro] = hexh[z]; ro = ro + 1; z = z + 1 } 2396 ro = of_catc(row, ro, 10) 2397 if of_append_line(logp, row, ro) != 0 { return 0 - 4 } 2398 let nsb: *u8 = sys_mmap(32) 2399 var nso: i64 = of_catn(nsb, 0, seq); nsb[nso] = 0 as u8 2400 let cert: *u8 = sys_mmap(OF_CERT_CAP) 2401 let cl: i64 = sc_cert(eid, doccid, nsb, hexh, cert) 2402 if cl <= 0 { return 0 - 4 } 2403 cid_of(cert, cl, out_cert_cid) 2404 let sprefix: *u8 = sys_mmap(600) 2405 var spo: i64 = of_cat(sprefix, 0, root); spo = of_cat(sprefix, spo, "/" as *u8); spo = of_cat(sprefix, spo, name); spo = of_cat(sprefix, spo, "/sign-" as *u8); sprefix[spo] = 0 as u8 2406 sc_cert_put(sprefix, eid, cert, cl) 2407 let certp: *u8 = sys_mmap(600) 2408 var cpo: i64 = of_cat(certp, 0, vd); cpo = of_cat(certp, cpo, "/cert.txt" as *u8); certp[cpo] = 0 as u8 2409 let ct: *u8 = sys_mmap(1024) 2410 var co: i64 = of_cat(ct, 0, "certificate=" as *u8); co = of_cat(ct, co, out_cert_cid); co = of_catc(ct, co, 10) 2411 co = of_cat(ct, co, "envelope=" as *u8); co = of_cat(ct, co, eid); co = of_catc(ct, co, 10) 2412 co = of_cat(ct, co, "document=" as *u8); co = of_cat(ct, co, doccid); co = of_catc(ct, co, 10) 2413 co = of_cat(ct, co, "signers=" as *u8); co = of_catn(ct, co, seq); co = of_catc(ct, co, 10) 2414 co = of_cat(ct, co, "audit_head=" as *u8) 2415 z = 0 2416 while z < OF_HEXSZ { ct[co] = hexh[z]; co = co + 1; z = z + 1 } 2417 co = of_catc(ct, co, 10) 2418 co = of_cat(ct, co, "status=completed" as *u8); co = of_catc(ct, co, 10) 2419 if of_write_file(certp, ct, co) != 0 { return 0 - 4 } 2420 let slp: *u8 = sys_mmap(600) 2421 var slo: i64 = of_cat(slp, 0, root); slo = of_cat(slp, slo, "/" as *u8); slo = of_cat(slp, slo, name); slo = of_cat(slp, slo, "/signatures.txt" as *u8); slp[slo] = 0 as u8 2422 let srow: *u8 = sys_mmap(512) 2423 var sro: i64 = of_cat(srow, 0, "v" as *u8); sro = of_catn(srow, sro, vn); sro = of_catc(srow, sro, 9); sro = of_cat(srow, sro, signer); sro = of_catc(srow, sro, 9); sro = of_catn(srow, sro, ts); sro = of_catc(srow, sro, 9); sro = of_cat(srow, sro, out_cert_cid); sro = of_catc(srow, sro, 10) 2424 of_append_line(slp, srow, sro) 2425 return 1 2426} 2427// /cert/<name>/v<N>: the human-readable signing receipt (text/plain), 404 when the version was never signed 2428func of_serve_cert(root: *u8, name: *u8, vn: i64, out: *u8, cap: i64) -> i64 { 2429 if of_cert_exists(root, name, vn) == 0 { return 0 - 1 } 2430 let vd: *u8 = sys_mmap(512) 2431 of_vdir(root, name, vn, vd) 2432 let cp: *u8 = sys_mmap(600) 2433 var co: i64 = of_cat(cp, 0, vd); co = of_cat(cp, co, "/cert.txt" as *u8); cp[co] = 0 as u8 2434 let szp: *i64 = sys_mmap(16) as *i64 2435 let b: *u8 = ss_readall(cp, szp) 2436 if (b as i64) == 0 { return 0 - 1 } 2437 var o: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: " as *u8) 2438 o = of_catn(out, o, szp[0]) 2439 o = of_cat(out, o, "\r\n\r\n" as *u8) 2440 if o + szp[0] > cap { sys_munmap(b, szp[0]); return 0 - 2 } 2441 var i: i64 = 0 2442 while i < szp[0] { out[o + i] = b[i]; i = i + 1 } 2443 sys_munmap(b, szp[0]) 2444 return o + szp[0] 2445} 2446// the import card on the home shell: a standard <input type=file>; the original is kept byte for byte as v1 2447func of_import_form(out: *u8, off: i64, base: *u8) -> i64 { 2448 var o: i64 = of_cat(out, off, "<div class='newt'><h3><div class='fico k0'>&uarr;</div>Import <span class='cnt'>.docx .odt</span></h3><form method='post' enctype='multipart/form-data' action='" as *u8) 2449 o = of_cat(out, o, base) 2450 o = of_cat(out, o, "/import'><p class='hint' style='margin:0'>Bring in a Word, Google Docs (export as .docx or .odt) or LibreOffice file. The original is kept byte for byte as v1; every edit after that is a new version.</p><p class='row'><input type='file' name='file' accept='.docx,.odt' required></p><p class='row'><input type='text' name='name' placeholder='file-name (blank = from the filename)'><button type='submit'>Import</button></p></form></div>\n" as *u8) 2451 return o 2452} 2453// the per-version Sign cell on the document page: receipt link when signed, then the consent-gated form 2454func of_sign_cell(out: *u8, off: i64, root: *u8, base: *u8, name: *u8, vn: i64) -> i64 { 2455 var o: i64 = off 2456 if of_cert_exists(root, name, vn) == 1 { 2457 o = of_cat(out, o, "<a href='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/cert/" as *u8); o = of_cat(out, o, name); o = of_cat(out, o, "/v" as *u8); o = of_catn(out, o, vn) 2458 o = of_cat(out, o, "' title='sealed completion certificate (CID over envelope, document, signers and audit head)'>&#10003; signed &middot; receipt</a><br>" as *u8) 2459 } 2460 o = of_cat(out, o, "<form method='post' action='" as *u8); o = of_cat(out, o, base); o = of_cat(out, o, "/sign' style='margin:0'><input type='hidden' name='name' value='" as *u8); o = of_cat(out, o, name) 2461 o = of_cat(out, o, "'><input type='hidden' name='version' value='" as *u8); o = of_catn(out, o, vn) 2462 o = of_cat(out, o, "'><input type='text' name='signer' placeholder='your handle' size='9' required> <label><input type='checkbox' name='consent' value='yes'> I agree to sign electronically (UETA/ESIGN consent)</label> <button type='submit' class='ghost' title='No consent, no signature: the ceremony refuses without it'>Sign</button></form>" as *u8) 2463 return o 2464} 2465// SESSION PROPAGATION for the no-JS path (the docportal pattern): when a session token is known, every same-app 2466// href='<base>/...' and action='<base>/...' in an HTML response gains ?s=<tok> (or &s= if a query exists) so a 2467// click keeps the session without cookies (C1). Rewrites in place into `out` (cap-bounded, REFUSES -> returns n 2468// unchanged if the rewritten page would not fit); non-HTML responses are returned untouched. 2469func of_propagate_tok(out: *u8, n: i64, base: *u8, tok: *u8, cap: i64) -> i64 { 2470 if tok[0] == (0 as u8) { return n } 2471 if of_memhas(out, n, "Content-Type: text/html" as *u8) == 0 { return n } 2472 let bl: i64 = of_slen(base) 2473 let tl: i64 = of_slen(tok) 2474 // one scratch page for the rewrite, UNMAPPED on every exit: a per-response map that is never released is the 2475 // exact leak class that took nx_opaque_login to 177 GB (2 MiB per response, never unmapped) 2476 let tmp: *u8 = sys_mmap(cap) 2477 var o: i64 = 0 2478 var i: i64 = 0 2479 var fits: i64 = 1 2480 while i < n { 2481 var hit: i64 = 0 2482 if out[i] == (61 as u8) { if i + 1 < n { if out[i + 1] == (39 as u8) { 2483 if i >= 4 { if of_memhas((out as i64 + i - 4) as *u8, 4, "href" as *u8) == 1 { hit = 1 } } 2484 if hit == 0 { if i >= 6 { if of_memhas((out as i64 + i - 6) as *u8, 6, "action" as *u8) == 1 { hit = 1 } } } 2485 if hit == 1 { 2486 var m: i64 = 1 2487 var k: i64 = 0 2488 while k < bl { if i + 2 + k >= n { m = 0; k = bl } else { if out[i + 2 + k] != base[k] { m = 0; k = bl } else { k = k + 1 } } } 2489 if m == 1 { if i + 2 + bl < n { if out[i + 2 + bl] != (47 as u8) { m = 0 } } else { m = 0 } } 2490 if m == 0 { hit = 0 } 2491 } 2492 } } } 2493 if hit == 1 { 2494 var j: i64 = i + 2 2495 var hasq: i64 = 0 2496 while j < n { if out[j] == (39 as u8) { break } if out[j] == (63 as u8) { hasq = 1 } j = j + 1 } 2497 if o + (j - i) + tl + 4 >= cap { fits = 0; i = n } else { 2498 var c: i64 = i 2499 while c < j { tmp[o] = out[c]; o = o + 1; c = c + 1 } 2500 if hasq == 1 { tmp[o] = 38 as u8 } else { tmp[o] = 63 as u8 } 2501 o = o + 1 2502 tmp[o] = 115 as u8; tmp[o + 1] = 61 as u8; o = o + 2 2503 var t: i64 = 0 2504 while t < tl { tmp[o] = tok[t]; o = o + 1; t = t + 1 } 2505 i = j 2506 } 2507 } else { 2508 if o + 1 >= cap { fits = 0; i = n } else { tmp[o] = out[i]; o = o + 1; i = i + 1 } 2509 } 2510 } 2511 var rn: i64 = n 2512 if fits == 1 { 2513 var k2: i64 = 0 2514 while k2 < o { out[k2] = tmp[k2]; k2 = k2 + 1 } 2515 rn = of_fix_content_length(out, o, cap) 2516 } 2517 sys_munmap(tmp, cap) 2518 return rn 2519} 2520// recompute "Content-Length: N" for an in-buffer HTTP response whose body length changed; returns the new total 2521func of_fix_content_length(out: *u8, n: i64, cap: i64) -> i64 { 2522 var hdr_end: i64 = 0 - 1 2523 var i: i64 = 0 2524 while i + 3 < n { if out[i] == (13 as u8) { if out[i+1] == (10 as u8) { if out[i+2] == (13 as u8) { if out[i+3] == (10 as u8) { hdr_end = i + 4; i = n } } } } i = i + 1 } 2525 if hdr_end < 0 { return n } 2526 let body: i64 = n - hdr_end 2527 let key: *u8 = "Content-Length: " as *u8 2528 let kl: i64 = of_slen(key) 2529 var p: i64 = 0 - 1 2530 var j: i64 = 0 2531 while j + kl < hdr_end { if p < 0 { if of_memhas((out as i64 + j) as *u8, kl, key) == 1 { if j == 0 { p = j } else { if out[j - 1] == (10 as u8) { p = j } } } } j = j + 1 } 2532 if p < 0 { return n } 2533 var q: i64 = p + kl 2534 while q < hdr_end { if out[q] == (13 as u8) { break } q = q + 1 } 2535 let tmp: *u8 = sys_mmap(cap) 2536 var o: i64 = 0 2537 var c: i64 = 0 2538 while c < p + kl { tmp[o] = out[c]; o = o + 1; c = c + 1 } 2539 o = of_catn(tmp, o, body) 2540 c = q 2541 var fits: i64 = 1 2542 while c < n { if o >= cap { fits = 0; c = n } else { tmp[o] = out[c]; o = o + 1; c = c + 1 } } 2543 var rn: i64 = n 2544 if fits == 1 { var k: i64 = 0; while k < o { out[k] = tmp[k]; k = k + 1 } rn = o } 2545 sys_munmap(tmp, cap) 2546 return rn 2547} 2548// OPEN-MODE wrapper: no handle -> no authz gating (current PUBLIC behavior; the 34-test offline gate runs here). 2549func of_handle(root: *u8, base: *u8, req: *u8, reqlen: i64, out: *u8, cap: i64) -> i64 { 2550 let mt: *u8 = sys_mmap(8); mt[0] = 0 as u8 2551 return of_handle_auth(root, base, req, reqlen, out, cap, mt, OF_AUTHZ, mt) 2552} 2553// AUTH-AWARE handler. handle = resolved caller ("" = unauthed/open). azprefix = ReBAC tuple store. tok = session 2554// token embedded in owner forms (zero-JS). A doc with NO owner tuple is PUBLIC; an OWNED doc: read needs 2555// rb_check(user:me, read, doc), a new version needs write, only the owner may share/unshare/manage. 2556func of_handle_auth(root: *u8, base: *u8, req: *u8, reqlen: i64, out: *u8, cap: i64, handle: *u8, azprefix: *u8, tok: *u8) -> i64 { 2557 var authed: i64 = 0; let me: *u8 = sys_mmap(320); me[0] = 0 as u8 2558 if handle[0] != (0 as u8) { authed = 1; of_meref(me, handle) } 2559 // fullpath = token between the first two spaces 2560 let fullpath: *u8 = sys_mmap(300) 2561 var i: i64 = 0 2562 while i < reqlen { if req[i] == (32 as u8) { i = i + 1; break } i = i + 1 } 2563 var t: i64 = 0 2564 while i < reqlen { if req[i] == (32 as u8) { break } if t < 299 { fullpath[t] = req[i]; t = t + 1 } i = i + 1 } 2565 fullpath[t] = 0 as u8 2566 // split off the query string (home search/sort/filter reads it) so routing sees a clean path 2567 let qs: *u8 = sys_mmap(300) 2568 qs[0] = 0 as u8 2569 var qi: i64 = 0 2570 while fullpath[qi] != (0 as u8) { 2571 if fullpath[qi] == (63 as u8) { 2572 var qq: i64 = qi + 1 2573 var qt: i64 = 0 2574 while fullpath[qq] != (0 as u8) { if qt < 299 { qs[qt] = fullpath[qq]; qt = qt + 1 } qq = qq + 1 } 2575 qs[qt] = 0 as u8 2576 fullpath[qi] = 0 as u8 2577 } else { qi = qi + 1 } 2578 } 2579 // strip the mount prefix -> path is relative to the app root ("/office/doc/x" -> "/doc/x", "/office" -> "") 2580 var path: *u8 = fullpath 2581 if base[0] != (0 as u8) { 2582 var bm: i64 = 1 2583 var bi: i64 = 0 2584 while base[bi] != (0 as u8) { if fullpath[bi] != base[bi] { bm = 0; bi = of_slen(base) } else { bi = bi + 1 } } 2585 if bm == 1 { path = (fullpath as i64 + of_slen(base)) as *u8 } 2586 } 2587 var is_post: i64 = 0 2588 if req[0] == (80 as u8) { if req[1] == (79 as u8) { is_post = 1 } } 2589 if is_post == 1 { 2590 var is_save: i64 = of_seq(path, "/save" as *u8) 2591 var is_restore: i64 = of_seq(path, "/restore" as *u8) 2592 var is_share: i64 = of_seq(path, "/share" as *u8) 2593 var is_unshare: i64 = of_seq(path, "/unshare" as *u8) 2594 var is_gadd: i64 = of_seq(path, "/group-add" as *u8) 2595 var is_gremove: i64 = of_seq(path, "/group-remove" as *u8) 2596 var is_ai: i64 = of_seq(path, "/ai" as *u8) 2597 var is_agent: i64 = of_seq(path, "/agent" as *u8) 2598 var is_star: i64 = of_seq(path, "/star" as *u8) 2599 var is_folder: i64 = of_seq(path, "/folder" as *u8) 2600 var is_import: i64 = of_seq(path, "/import" as *u8) 2601 var is_sign: i64 = of_seq(path, "/sign" as *u8) 2602 if (is_save + is_restore + is_share + is_unshare + is_gadd + is_gremove + is_ai + is_agent + is_star + is_folder + is_import + is_sign) == 0 { return of_err(out, "404 Not Found" as *u8, "no such POST route" as *u8) } 2603 // same-origin guard: if Origin present it must contain our Host 2604 let ob: *u8 = sys_mmap(300) 2605 let hb: *u8 = sys_mmap(300) 2606 of_hdr_get(req, reqlen, "Origin:" as *u8, ob, 300) 2607 of_hdr_get(req, reqlen, "Host:" as *u8, hb, 300) 2608 if ob[0] != (0 as u8) { if hb[0] != (0 as u8) { 2609 if of_memhas(ob, of_slen(ob), hb) == 0 { return of_err(out, "403 Forbidden" as *u8, "cross-origin POST refused" as *u8) } 2610 } } 2611 var bs: i64 = 0 - 1 2612 var j: i64 = 0 2613 while j + 3 < reqlen { 2614 if req[j] == (13 as u8) { if req[j+1] == (10 as u8) { if req[j+2] == (13 as u8) { if req[j+3] == (10 as u8) { bs = j + 4; j = reqlen } } } } 2615 j = j + 1 2616 } 2617 if bs < 0 { return of_err(out, "400 Bad Request" as *u8, "no body" as *u8) } 2618 let body: *u8 = (req as i64 + bs) as *u8 2619 let blen: i64 = reqlen - bs 2620 // IMPORT (LP1): a multipart upload lands as v1 of a NEW document; the original bytes are kept byte for byte. 2621 if is_import == 1 { 2622 // a truncated body is refused LOUDLY: the daemon's request buffer is a NAMED ceiling, never a silent cut 2623 let clb: *u8 = sys_mmap(32) 2624 of_hdr_get(req, reqlen, "Content-Length:" as *u8, clb, 32) 2625 if of_atoi(clb) > blen { return of_err(out, "413 Payload Too Large" as *u8, "the upload is larger than the office request buffer; split the document or raise the daemon's request ceiling" as *u8) } 2626 let bnd: *u8 = sys_mmap(256) 2627 if of_ct_boundary(req, reqlen, bnd, 256) <= 0 { return of_err(out, "400 Bad Request" as *u8, "import needs a multipart/form-data upload" as *u8) } 2628 let parts: *MultipartPart = sys_mmap(32 * OF_IMPORT_MAXPARTS) as *MultipartPart 2629 let np: i64 = multipart_parse(body, blen, bnd, of_slen(bnd), parts, OF_IMPORT_MAXPARTS) 2630 if np <= 0 { return of_err(out, "400 Bad Request" as *u8, "malformed multipart upload" as *u8) } 2631 let inm: *u8 = sys_mmap(64) 2632 let ifn: *u8 = sys_mmap(256) 2633 let pnm: *u8 = sys_mmap(64) 2634 var foff: i64 = 0 - 1 2635 var flen: i64 = 0 2636 inm[0] = 0 as u8 2637 ifn[0] = 0 as u8 2638 var pi: i64 = 0 2639 while pi < np { 2640 let pp: *MultipartPart = ((parts as i64) + pi * 32) as *MultipartPart 2641 of_cd_extract(body, pp.headers_off, pp.headers_len, "name=\"" as *u8, pnm, 64) 2642 if of_seq(pnm, "file" as *u8) == 1 { foff = pp.body_off; flen = pp.body_len; of_cd_extract(body, pp.headers_off, pp.headers_len, "filename=\"" as *u8, ifn, 256) } 2643 if of_seq(pnm, "name" as *u8) == 1 { var w: i64 = 0; while w < pp.body_len { if w < 63 { inm[w] = body[pp.body_off + w] } w = w + 1 } if pp.body_len < 63 { inm[pp.body_len] = 0 as u8 } else { inm[63] = 0 as u8 } } 2644 pi = pi + 1 2645 } 2646 if flen <= 0 { return of_err(out, "400 Bad Request" as *u8, "no file part in the upload" as *u8) } 2647 if inm[0] == (0 as u8) { of_name_from_filename(ifn, inm) } 2648 if of_name_ok(inm) == 0 { return of_err(out, "400 Bad Request" as *u8, "invalid name (a-z 0-9 dash, max 40) -- give the import a name" as *u8) } 2649 let irc: i64 = of_import(root, base, inm, ifn, (body as i64 + foff) as *u8, flen) 2650 if irc == 1 { 2651 if authed == 1 { let dref2: *u8 = sys_mmap(320); of_docref(dref2, inm); rb_put(azprefix, dref2, "owner" as *u8, me, handle, 1) } 2652 var io2: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2653 io2 = of_cat(out, io2, base); io2 = of_cat(out, io2, "/doc/" as *u8); io2 = of_cat(out, io2, inm); io2 = of_cat(out, io2, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2654 return io2 2655 } 2656 if irc == (0 - 2) { return of_err(out, "409 Conflict" as *u8, "that name already exists -- import creates a new document; pick another name" as *u8) } 2657 if irc == (0 - 3) { return of_err(out, "415 Unsupported Media Type" as *u8, "not a .docx or .odt package (Word, Google Docs export or LibreOffice Writer files only)" as *u8) } 2658 if irc == (0 - 4) { return of_err(out, "422 Unprocessable Entity" as *u8, "the document package could not be read" as *u8) } 2659 if irc == (0 - 6) { return of_err(out, "422 Unprocessable Entity" as *u8, "no readable paragraphs in that document" as *u8) } 2660 return of_err(out, "500 Internal Server Error" as *u8, "import failed while converting or writing the version" as *u8) 2661 } 2662 // SIGN (LP4): the consent-gated ceremony over one version; refused without consent; needs read access 2663 if is_sign == 1 { 2664 let snm2: *u8 = sys_mmap(64) 2665 let svs: *u8 = sys_mmap(16) 2666 let sgn: *u8 = sys_mmap(64) 2667 let cns: *u8 = sys_mmap(8) 2668 of_form_get(body, blen, "name" as *u8, snm2, 64) 2669 of_form_get(body, blen, "version" as *u8, svs, 16) 2670 of_form_get(body, blen, "signer" as *u8, sgn, 64) 2671 of_form_get(body, blen, "consent" as *u8, cns, 8) 2672 if of_name_ok(snm2) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 2673 if of_read_ok(azprefix, me, authed, snm2) == 0 { return of_deny_read(out) } 2674 let ccid: *u8 = sys_mmap(128) 2675 let src: i64 = of_sign_version(root, snm2, of_atoi(svs), sgn, cns, ccid) 2676 if src == 1 { 2677 var so2: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2678 so2 = of_cat(out, so2, base); so2 = of_cat(out, so2, "/doc/" as *u8); so2 = of_cat(out, so2, snm2); so2 = of_cat(out, so2, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2679 return so2 2680 } 2681 if src == (0 - 2) { return of_err(out, "403 Forbidden" as *u8, "no consent, no signature: tick the consent box (UETA/ESIGN intent and consent to transact electronically)" as *u8) } 2682 if src == (0 - 3) { return of_err(out, "400 Bad Request" as *u8, "signer must be a simple handle (a-z 0-9 dash underscore)" as *u8) } 2683 if src == (0 - 1) { return of_err(out, "404 Not Found" as *u8, "no such file or version" as *u8) } 2684 return of_err(out, "500 Internal Server Error" as *u8, "the signing record could not be written" as *u8) 2685 } 2686 // SHARE / UNSHARE an owned doc (owner-only; additive grant / tombstone revoke). GROUP add/remove members. 2687 if is_share == 1 { return of_do_share(base, azprefix, me, handle, authed, body, blen, out, 1) } 2688 if is_unshare == 1 { return of_do_share(base, azprefix, me, handle, authed, body, blen, out, 0) } 2689 if is_gadd == 1 { return of_do_group(base, azprefix, me, handle, authed, body, blen, out, 1) } 2690 if is_gremove == 1 { return of_do_group(base, azprefix, me, handle, authed, body, blen, out, 0) } 2691 // AI CONTINUE: draft a continuation with OUR OWN sovereign 0.5B model (:11434) + append it as a NEW 2692 // version (additive -- the AI draft is a version you can diff/restore). Doc kind only. Graceful 503 if 2693 // the seat is down. Write-gated like a save (owned docs need edit access). 2694 if is_ai == 1 { 2695 let anm: *u8 = sys_mmap(64) 2696 of_form_get(body, blen, "name" as *u8, anm, 64) 2697 if of_name_ok(anm) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 2698 if of_write_ok(azprefix, me, authed, anm) == 0 { return of_deny_write(out) } 2699 let akb: *u8 = sys_mmap(64) 2700 let avc: i64 = of_manifest_count(root, anm, akb, 64) 2701 if avc <= 0 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 2702 // ONE sovereign seat, THREE kinds. The prompt AND the append are kind-specific so the model edits each 2703 // artifact in ITS OWN grammar: prose for a doc, an insight ROW for a sheet (OF-A2, the "Fill with 2704 // Gemini" class), a whole new SLIDE for a deck (OF-A3, prompt-to-slide). Every kind stays additive. 2705 let akind: i64 = of_kind_idx(akb) 2706 let aspec: *u8 = sys_mmap(131073) 2707 let asl: i64 = of_read_version_spec(root, anm, avc, aspec, 131072) 2708 let ptext: *u8 = sys_mmap(2048) 2709 let ptl: i64 = of_spec_to_text(aspec, asl, ptext, 1200) 2710 let aprompt: *u8 = sys_mmap(4096) 2711 var api: i64 = 0 2712 if akind == 1 { api = of_ai_prompt_sheet(ptext, aprompt) } else { 2713 if akind == 2 { api = of_ai_prompt_deck(ptext, aprompt) } else { api = of_cat(aprompt, 0, ptext) } 2714 } 2715 aprompt[api] = 0 as u8 2716 let comp: *u8 = sys_mmap(8192) 2717 let cl: i64 = of_llm_complete(aprompt, api, comp, 8000) 2718 if cl <= 0 { return of_err(out, "503 Service Unavailable" as *u8, "the sovereign AI seat (our own 0.5B model on :11434) is not answering -- start nx_f32_llm_serve or try again" as *u8) } 2719 let nspec: *u8 = sys_mmap(140000) 2720 var no: i64 = 0 2721 var ci: i64 = 0 2722 while ci < asl { nspec[no] = aspec[ci]; no = no + 1; ci = ci + 1 } 2723 if no > 0 { if nspec[no-1] != (10 as u8) { nspec[no] = 10 as u8; no = no + 1 } } 2724 if akind == 2 { 2725 // deck: everything up to the first sentence end becomes the TITLE, the remainder the BULLET 2726 var dsp: i64 = 0 - 1 2727 var dfi: i64 = 0 2728 while dfi < cl { if comp[dfi] == (46 as u8) { dsp = dfi; dfi = cl } else { dfi = dfi + 1 } } 2729 var tend: i64 = cl 2730 if dsp > 3 { tend = dsp } 2731 no = of_cat(nspec, no, "S " as *u8) 2732 var dti: i64 = 0 2733 while dti < tend { let tc: i64 = comp[dti] as i64; if tc == 10 { nspec[no] = 32 as u8 } else { if tc == 9 { nspec[no] = 32 as u8 } else { nspec[no] = comp[dti] } } no = no + 1; dti = dti + 1 } 2734 if dsp > 3 { if dsp + 2 < cl { 2735 no = of_catc(nspec, no, 10) 2736 no = of_cat(nspec, no, "B " as *u8) 2737 var dbi: i64 = dsp + 1 2738 while dbi < cl { let bc: i64 = comp[dbi] as i64; if bc == 10 { nspec[no] = 32 as u8 } else { if bc == 9 { nspec[no] = 32 as u8 } else { nspec[no] = comp[dbi] } } no = no + 1; dbi = dbi + 1 } 2739 } } 2740 } else { 2741 // sheet -> a REAL two-cell TSV row so the insight lands IN the grid; doc -> a P paragraph 2742 if akind == 1 { no = of_cat(nspec, no, "AI insight" as *u8); no = of_catc(nspec, no, 9) } else { no = of_cat(nspec, no, "P " as *u8) } 2743 var di: i64 = 0 2744 while di < cl { let c: i64 = comp[di] as i64; if c == 10 { nspec[no] = 32 as u8 } else { if c == 9 { nspec[no] = 32 as u8 } else { nspec[no] = comp[di] } } no = no + 1; di = di + 1 } 2745 } 2746 nspec[no] = 0 as u8 2747 let nvn: i64 = of_save(root, base, anm, akb, nspec, no, 0) 2748 if nvn > 0 { 2749 var ao: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2750 ao = of_cat(out, ao, base); ao = of_cat(out, ao, "/doc/" as *u8); ao = of_cat(out, ao, anm); ao = of_cat(out, ao, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2751 return ao 2752 } 2753 return of_err(out, "500 Internal Server Error" as *u8, "AI draft save failed" as *u8) 2754 } 2755 // AGENT MODE (OF-A4, the 2026 marquee): ONE POST = ONE agent turn. PLAN when there is no plan yet (or 2756 // a fresh goal arrives), otherwise EXECUTE the next step, and once every step is drafted run one final 2757 // REFINE turn. Each executed turn lands as a NEW VERSION, so the whole trajectory is diffable/restorable. 2758 // D is bumped ONLY AFTER its version lands, so a 503 mid-run is safely retryable (no step is skipped). 2759 if is_agent == 1 { 2760 let gnm: *u8 = sys_mmap(64) 2761 of_form_get(body, blen, "name" as *u8, gnm, 64) 2762 if of_name_ok(gnm) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 2763 if of_write_ok(azprefix, me, authed, gnm) == 0 { return of_deny_write(out) } 2764 let gkb: *u8 = sys_mmap(64) 2765 let gvc: i64 = of_manifest_count(root, gnm, gkb, 64) 2766 if gvc <= 0 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 2767 if of_kind_idx(gkb) != 0 { return of_err(out, "400 Bad Request" as *u8, "agent mode is for documents (doc kind) only" as *u8) } 2768 let goal: *u8 = sys_mmap(512) 2769 of_form_get(body, blen, "goal" as *u8, goal, 512) 2770 let ast: *u8 = sys_mmap(8192) 2771 let an: i64 = of_agent_read(root, gnm, ast, 8000) 2772 // ground EVERY turn in the CURRENT document, not the one the plan was written against 2773 let gspec: *u8 = sys_mmap(131073) 2774 let gsl: i64 = of_read_version_spec(root, gnm, gvc, gspec, 131072) 2775 let gtext: *u8 = sys_mmap(2048) 2776 let gtl: i64 = of_spec_to_text(gspec, gsl, gtext, 1100) 2777 let agloc: *u8 = sys_mmap(512) 2778 2779 // ---- PLAN turn ---- 2780 var want_plan: i64 = 0 2781 if an <= 0 { want_plan = 1 } 2782 if of_slen(goal) > 0 { want_plan = 1 } 2783 if want_plan == 1 { 2784 if of_slen(goal) == 0 { return of_err(out, "400 Bad Request" as *u8, "agent mode needs a goal to plan against" as *u8) } 2785 let pp: *u8 = sys_mmap(4096) 2786 var po2: i64 = of_cat(pp, 0, "You are planning edits to a document. Goal: " as *u8) 2787 po2 = of_cat(pp, po2, goal) 2788 po2 = of_cat(pp, po2, ". Document so far: " as *u8) 2789 po2 = of_cat(pp, po2, gtext) 2790 po2 = of_cat(pp, po2, " . List the steps, one per line:" as *u8) 2791 pp[po2] = 0 as u8 2792 let pcomp: *u8 = sys_mmap(8192) 2793 let pcl: i64 = of_llm_complete_n(pp, po2, pcomp, 8000, 32) 2794 if pcl <= 0 { return of_err(out, "503 Service Unavailable" as *u8, "the sovereign AI seat (our own 0.5B model on :11434) is not answering -- start nx_f32_llm_serve or try again" as *u8) } 2795 let plan: *u8 = sys_mmap(4096) 2796 let nst: i64 = of_agent_plan_parse(pcomp, pcl, plan, 4000) 2797 if nst <= 0 { return of_err(out, "502 Bad Gateway" as *u8, "the model returned no usable plan -- try a more specific goal" as *u8) } 2798 let nstate: *u8 = sys_mmap(8192) 2799 var so2: i64 = of_cat(nstate, 0, "G " as *u8) 2800 so2 = of_cat(nstate, so2, goal) 2801 so2 = of_catc(nstate, so2, 10) 2802 so2 = of_cat(nstate, so2, plan) 2803 so2 = of_cat(nstate, so2, "D 0\n" as *u8) 2804 nstate[so2] = 0 as u8 2805 if of_agent_write(root, gnm, nstate, so2) != 0 { return of_err(out, "500 Internal Server Error" as *u8, "agent plan save failed" as *u8) } 2806 var pl: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2807 pl = of_cat(out, pl, base); pl = of_cat(out, pl, "/doc/" as *u8); pl = of_cat(out, pl, gnm) 2808 pl = of_cat(out, pl, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2809 return pl 2810 } 2811 2812 // ---- EXECUTE / REFINE turn ---- 2813 let nsteps: i64 = of_agent_tagcount(ast, an, 83) 2814 let dn: i64 = of_agent_done(ast, an) 2815 if dn > nsteps { return of_err(out, "409 Conflict" as *u8, "this agent run is already complete -- give it a new goal to start another" as *u8) } 2816 let gg: *u8 = sys_mmap(512) 2817 of_agent_tagline(ast, an, 71, 0, gg, 512) 2818 let sp: *u8 = sys_mmap(4096) 2819 var qo: i64 = 0 2820 if dn < nsteps { 2821 let stx: *u8 = sys_mmap(256) 2822 of_agent_tagline(ast, an, 83, dn, stx, 256) 2823 qo = of_cat(sp, 0, "Goal: " as *u8) 2824 qo = of_cat(sp, qo, gg) 2825 qo = of_cat(sp, qo, ". Now do step " as *u8) 2826 qo = of_catn(sp, qo, dn + 1) 2827 qo = of_cat(sp, qo, ": " as *u8) 2828 qo = of_cat(sp, qo, stx) 2829 qo = of_cat(sp, qo, ". Document so far: " as *u8) 2830 qo = of_cat(sp, qo, gtext) 2831 qo = of_cat(sp, qo, " . Write that section:" as *u8) 2832 } else { 2833 qo = of_cat(sp, 0, "Goal: " as *u8) 2834 qo = of_cat(sp, qo, gg) 2835 qo = of_cat(sp, qo, ". Every step is drafted. Document: " as *u8) 2836 qo = of_cat(sp, qo, gtext) 2837 qo = of_cat(sp, qo, " . Write a short closing paragraph that ties it together:" as *u8) 2838 } 2839 sp[qo] = 0 as u8 2840 let scomp: *u8 = sys_mmap(8192) 2841 let scl: i64 = of_llm_complete(sp, qo, scomp, 8000) 2842 if scl <= 0 { return of_err(out, "503 Service Unavailable" as *u8, "the sovereign AI seat (our own 0.5B model on :11434) is not answering -- the agent kept its place, retry this step" as *u8) } 2843 let gnspec: *u8 = sys_mmap(140000) 2844 var gno: i64 = 0 2845 var gci: i64 = 0 2846 while gci < gsl { gnspec[gno] = gspec[gci]; gno = gno + 1; gci = gci + 1 } 2847 if gno > 0 { if gnspec[gno-1] != (10 as u8) { gnspec[gno] = 10 as u8; gno = gno + 1 } } 2848 gno = of_cat(gnspec, gno, "P " as *u8) 2849 var gdi: i64 = 0 2850 while gdi < scl { 2851 let gc: i64 = scomp[gdi] as i64 2852 if gc == 10 { gnspec[gno] = 32 as u8 } else { if gc == 9 { gnspec[gno] = 32 as u8 } else { gnspec[gno] = scomp[gdi] } } 2853 gno = gno + 1; gdi = gdi + 1 2854 } 2855 gnspec[gno] = 0 as u8 2856 let gvn: i64 = of_save(root, base, gnm, gkb, gnspec, gno, 0) 2857 if gvn <= 0 { return of_err(out, "500 Internal Server Error" as *u8, "agent step save failed" as *u8) } 2858 // the version landed -- NOW advance the cursor 2859 let ns2: *u8 = sys_mmap(8192) 2860 let sbuf: *u8 = sys_mmap(256) 2861 var xo: i64 = of_cat(ns2, 0, "G " as *u8) 2862 xo = of_cat(ns2, xo, gg) 2863 xo = of_catc(ns2, xo, 10) 2864 var si: i64 = 0 2865 while si < nsteps { 2866 of_agent_tagline(ast, an, 83, si, sbuf, 256) 2867 xo = of_cat(ns2, xo, "S " as *u8) 2868 xo = of_cat(ns2, xo, sbuf) 2869 xo = of_catc(ns2, xo, 10) 2870 si = si + 1 2871 } 2872 xo = of_cat(ns2, xo, "D " as *u8) 2873 xo = of_catn(ns2, xo, dn + 1) 2874 xo = of_catc(ns2, xo, 10) 2875 ns2[xo] = 0 as u8 2876 of_agent_write(root, gnm, ns2, xo) 2877 var al: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2878 al = of_cat(out, al, base); al = of_cat(out, al, "/doc/" as *u8); al = of_cat(out, al, gnm) 2879 al = of_cat(out, al, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2880 return al 2881 } 2882 // U3 STAR / FOLDER: library organisation, write-gated exactly like a save so a reader cannot reorganise 2883 // someone else's library. Neither touches the document spec or its versions. 2884 if is_star == 1 { 2885 let snm: *u8 = sys_mmap(64) 2886 of_form_get(body, blen, "name" as *u8, snm, 64) 2887 if of_name_ok(snm) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 2888 if of_write_ok(azprefix, me, authed, snm) == 0 { return of_deny_write(out) } 2889 let skb: *u8 = sys_mmap(64) 2890 if of_manifest_count(root, snm, skb, 64) <= 0 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 2891 of_star_toggle(root, snm) 2892 var so: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other 2893 2894Location: " as *u8) 2895 so = of_cat(out, so, base); so = of_cat(out, so, "/" as *u8) 2896 so = of_cat(out, so, " 2897 2898Content-Length: 0 2899 2900Connection: close 2901 2902 2903 2904" as *u8) 2905 return so 2906 } 2907 if is_folder == 1 { 2908 let fnm: *u8 = sys_mmap(64) 2909 let fvl: *u8 = sys_mmap(64) 2910 of_form_get(body, blen, "name" as *u8, fnm, 64) 2911 of_form_get(body, blen, "folder" as *u8, fvl, 48) 2912 if of_name_ok(fnm) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 2913 if of_write_ok(azprefix, me, authed, fnm) == 0 { return of_deny_write(out) } 2914 let fkb: *u8 = sys_mmap(64) 2915 if of_manifest_count(root, fnm, fkb, 64) <= 0 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 2916 // a folder is a plain label; reuse the handle validator so it cannot carry separators or markup 2917 if fvl[0] != (0 as u8) { if of_tok_ok(fvl) == 0 { return of_err(out, "400 Bad Request" as *u8, "folder name must be simple (a-z 0-9 dash underscore)" as *u8) } } 2918 of_folder_set(root, fnm, fvl) 2919 var fo: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other 2920 2921Location: " as *u8) 2922 fo = of_cat(out, fo, base); fo = of_cat(out, fo, "/doc/" as *u8); fo = of_cat(out, fo, fnm) 2923 fo = of_cat(out, fo, " 2924 2925Content-Length: 0 2926 2927Connection: close 2928 2929 2930 2931" as *u8) 2932 return fo 2933 } 2934 // RESTORE: put an old version back by SAVING its spec as a NEW version (additive -- never destroys history). 2935 if is_restore == 1 { 2936 let rnm: *u8 = sys_mmap(64) 2937 let rvs: *u8 = sys_mmap(16) 2938 of_form_get(body, blen, "name" as *u8, rnm, 64) 2939 of_form_get(body, blen, "version" as *u8, rvs, 16) 2940 if of_name_ok(rnm) == 0 { return of_err(out, "400 Bad Request" as *u8, "bad name" as *u8) } 2941 if of_write_ok(azprefix, me, authed, rnm) == 0 { return of_deny_write(out) } 2942 let rkb: *u8 = sys_mmap(64) 2943 let rvc: i64 = of_manifest_count(root, rnm, rkb, 64) 2944 if rvc <= 0 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 2945 let rv: i64 = of_atoi(rvs) 2946 if rv < 1 { return of_err(out, "400 Bad Request" as *u8, "bad version" as *u8) } 2947 if rv > rvc { return of_err(out, "400 Bad Request" as *u8, "bad version" as *u8) } 2948 let rspec: *u8 = sys_mmap(131073) 2949 let rsl: i64 = of_read_version_spec(root, rnm, rv, rspec, 131072) 2950 let rnew: i64 = of_save(root, base, rnm, rkb, rspec, rsl, 0) 2951 if rnew > 0 { 2952 var ro2: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2953 ro2 = of_cat(out, ro2, base); ro2 = of_cat(out, ro2, "/doc/" as *u8); ro2 = of_cat(out, ro2, rnm); ro2 = of_cat(out, ro2, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2954 return ro2 2955 } 2956 return of_err(out, "500 Internal Server Error" as *u8, "restore failed (organ rejected the spec)" as *u8) 2957 } 2958 let nm: *u8 = sys_mmap(64) 2959 let kd: *u8 = sys_mmap(32) 2960 let spec: *u8 = sys_mmap(131073) 2961 of_form_get(body, blen, "name" as *u8, nm, 64) 2962 of_form_get(body, blen, "kind" as *u8, kd, 32) 2963 let sl: i64 = of_form_get(body, blen, "spec" as *u8, spec, 131073) 2964 // AUTHZ: an OWNED doc's new version needs write access; remember owned-ness to CLAIM on first save. 2965 var was_owned: i64 = 0 2966 if of_name_ok(nm) == 1 { let dref0: *u8 = sys_mmap(320); of_docref(dref0, nm); if rb_obj_has_owner(azprefix, dref0) == 1 { was_owned = 1 } } 2967 if was_owned == 1 { if of_write_ok(azprefix, me, authed, nm) == 0 { return of_deny_write(out) } } 2968 // ajax=1 = background AUTOSAVE (fetch from office_app.js): answer 200 OK v<N> instead of the 303 2969 let ax: *u8 = sys_mmap(8) 2970 of_form_get(body, blen, "ajax" as *u8, ax, 8) 2971 var auto: i64 = 0 2972 if ax[0] == (49 as u8) { auto = 1 } 2973 let vn: i64 = of_save(root, base, nm, kd, spec, sl, auto) 2974 if vn > 0 { 2975 // CLAIM ownership on first save by an authed user: unowned doc -> owner tuple (now private + shareable). 2976 if was_owned == 0 { if authed == 1 { let dref1: *u8 = sys_mmap(320); of_docref(dref1, nm); rb_put(azprefix, dref1, "owner" as *u8, me, handle, 1) } } 2977 if auto == 1 { 2978 // body = "OK v" + vn + "\n" (4 + digits(vn) + 1) -> Content-Length so strict clients frame it. 2979 var nd: i64 = 1 2980 var tv: i64 = vn 2981 while tv >= 10 { nd = nd + 1; tv = tv / 10 } 2982 var oa: i64 = of_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: " as *u8) 2983 oa = of_catn(out, oa, 4 + nd + 1) 2984 oa = of_cat(out, oa, "\r\nConnection: close\r\n\r\nOK v" as *u8) 2985 oa = of_catn(out, oa, vn) 2986 oa = of_catc(out, oa, 10) 2987 return oa 2988 } 2989 var o: i64 = of_cat(out, 0, "HTTP/1.1 303 See Other\r\nLocation: " as *u8) 2990 o = of_cat(out, o, base) 2991 o = of_cat(out, o, "/doc/" as *u8) 2992 o = of_cat(out, o, nm) 2993 o = of_cat(out, o, "\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" as *u8) 2994 return o 2995 } 2996 if vn == (0 - 2) { 2997 // a refusal that knows the remedy must NAME it: which kind holds the name, and where to open it 2998 let ek: *u8 = sys_mmap(64) 2999 of_manifest_count(root, nm, ek, 64) 3000 let msg: *u8 = sys_mmap(512) 3001 var mo: i64 = of_cat(msg, 0, "kind mismatch: '" as *u8) 3002 mo = of_cat(msg, mo, nm) 3003 mo = of_cat(msg, mo, "' already exists as a " as *u8) 3004 mo = of_cat(msg, mo, of_kind_name(of_kind_idx(ek))) 3005 mo = of_cat(msg, mo, " -- open " as *u8) 3006 mo = of_cat(msg, mo, base) 3007 mo = of_cat(msg, mo, "/doc/" as *u8) 3008 mo = of_cat(msg, mo, nm) 3009 mo = of_cat(msg, mo, " to edit it, or choose a new name" as *u8) 3010 msg[mo] = 0 as u8 3011 let en: i64 = of_err(out, "400 Bad Request" as *u8, msg) 3012 sys_munmap(msg, 512) 3013 sys_munmap(ek, 64) 3014 return en 3015 } 3016 if vn == (0 - 3) { return of_err(out, "500 Internal Server Error" as *u8, "the format organ rejected the spec (build failed)" as *u8) } 3017 if vn == (0 - 4) { return of_err(out, "500 Internal Server Error" as *u8, "preview render failed" as *u8) } 3018 return of_err(out, "400 Bad Request" as *u8, "invalid name (a-z 0-9 dash, max 40), kind, or empty spec" as *u8) 3019 } 3020 // GET routes 3021 if of_seq(path, "/app.js" as *u8) == 1 { return of_serve_js(out, cap) } 3022 if of_seq(path, "/sw.js" as *u8) == 1 { return of_serve_sw(out, cap) } 3023 if of_seq(path, "/manifest.webmanifest" as *u8) == 1 { return of_serve_manifest(out, base, cap) } 3024 if of_seq(path, "/" as *u8) == 1 { return of_cl_frame(out, of_home(root, base, qs, out, cap, azprefix, me, authed), cap) } 3025 if path[0] == (0 as u8) { return of_cl_frame(out, of_home(root, base, qs, out, cap, azprefix, me, authed), cap) } 3026 if of_starts(path, "/doc/" as *u8) == 1 { 3027 let nm: *u8 = sys_mmap(64) 3028 var q: i64 = 5 3029 var t2: i64 = 0 3030 while path[q] != (0 as u8) { if t2 < 63 { nm[t2] = path[q]; t2 = t2 + 1 } q = q + 1 } 3031 nm[t2] = 0 as u8 3032 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3033 if of_read_ok(azprefix, me, authed, nm) == 0 { return of_deny_read(out) } 3034 let n: i64 = of_docpage(root, base, nm, out, cap) 3035 if n < 0 { return of_err(out, "404 Not Found" as *u8, "no such file" as *u8) } 3036 return of_cl_frame(out, n, cap) 3037 } 3038 if of_starts(path, "/preview/" as *u8) == 1 { 3039 let nm: *u8 = sys_mmap(64) 3040 let vn: i64 = of_parse_nv(path, 9, nm, 64) 3041 if vn < 1 { return of_err(out, "404 Not Found" as *u8, "bad preview path" as *u8) } 3042 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3043 if of_read_ok(azprefix, me, authed, nm) == 0 { return of_deny_read(out) } 3044 let n: i64 = of_serve(root, nm, vn, 1, out, cap) 3045 if n < 0 { return of_err(out, "404 Not Found" as *u8, "no such version" as *u8) } 3046 return n 3047 } 3048 if of_starts(path, "/file/" as *u8) == 1 { 3049 let nm: *u8 = sys_mmap(64) 3050 let vn: i64 = of_parse_nv(path, 6, nm, 64) 3051 if vn < 1 { return of_err(out, "404 Not Found" as *u8, "bad file path" as *u8) } 3052 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3053 if of_read_ok(azprefix, me, authed, nm) == 0 { return of_deny_read(out) } 3054 let n: i64 = of_serve(root, nm, vn, 0, out, cap) 3055 if n < 0 { return of_err(out, "404 Not Found" as *u8, "no such version" as *u8) } 3056 return n 3057 } 3058 if of_starts(path, "/original/" as *u8) == 1 { 3059 // LP1: the untouched upload bytes of an imported version (original.odt | original.docx), else the version file 3060 let nm: *u8 = sys_mmap(64) 3061 let vn: i64 = of_parse_nv(path, 10, nm, 64) 3062 if vn < 1 { return of_err(out, "404 Not Found" as *u8, "bad original path" as *u8) } 3063 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3064 if of_read_ok(azprefix, me, authed, nm) == 0 { return of_deny_read(out) } 3065 let n: i64 = of_serve_original(root, nm, vn, out, cap) 3066 if n < 0 { return of_err(out, "404 Not Found" as *u8, "no such version" as *u8) } 3067 return n 3068 } 3069 if of_starts(path, "/cert/" as *u8) == 1 { 3070 // LP4: the signing receipt of a version (certificate CID, envelope, document CID, signers, audit head) 3071 let nm: *u8 = sys_mmap(64) 3072 let vn: i64 = of_parse_nv(path, 6, nm, 64) 3073 if vn < 1 { return of_err(out, "404 Not Found" as *u8, "bad cert path" as *u8) } 3074 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3075 if of_read_ok(azprefix, me, authed, nm) == 0 { return of_deny_read(out) } 3076 let n: i64 = of_serve_cert(root, nm, vn, out, cap) 3077 if n < 0 { return of_err(out, "404 Not Found" as *u8, "this version has not been signed" as *u8) } 3078 return n 3079 } 3080 if of_starts(path, "/diff/" as *u8) == 1 { 3081 // /diff/<name>/<a>/<b> 3082 let nm: *u8 = sys_mmap(64) 3083 var q: i64 = 6 3084 var t: i64 = 0 3085 while path[q] != (0 as u8) { if path[q] == (47 as u8) { break } if t < 63 { nm[t] = path[q]; t = t + 1 } q = q + 1 } 3086 nm[t] = 0 as u8 3087 if path[q] != (47 as u8) { return of_err(out, "404 Not Found" as *u8, "bad diff path" as *u8) } 3088 q = q + 1 3089 var va: i64 = 0; var da: i64 = 0 3090 while path[q] != (0 as u8) { let c: i64 = path[q] as i64; if c >= 48 { if c <= 57 { va = va * 10 + (c - 48); da = da + 1; q = q + 1 } else { break } } else { break } } 3091 if path[q] != (47 as u8) { return of_err(out, "404 Not Found" as *u8, "bad diff path" as *u8) } 3092 q = q + 1 3093 var vb: i64 = 0; var db: i64 = 0 3094 while path[q] != (0 as u8) { let c: i64 = path[q] as i64; if c >= 48 { if c <= 57 { vb = vb * 10 + (c - 48); db = db + 1; q = q + 1 } else { break } } else { break } } 3095 if da == 0 { return of_err(out, "404 Not Found" as *u8, "bad diff versions" as *u8) } 3096 if db == 0 { return of_err(out, "404 Not Found" as *u8, "bad diff versions" as *u8) } 3097 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3098 if of_read_ok(azprefix, me, authed, nm) == 0 { return of_deny_read(out) } 3099 let n: i64 = of_diffpage(root, base, nm, va, vb, out, cap) 3100 if n < 0 { return of_err(out, "404 Not Found" as *u8, "no such file or version" as *u8) } 3101 return of_cl_frame(out, n, cap) 3102 } 3103 if of_seq(path, "/groups" as *u8) == 1 { 3104 let n: i64 = of_groupspage(base, azprefix, me, authed, tok, out, cap) 3105 return of_cl_frame(out, n, cap) 3106 } 3107 if of_seq(path, "/shared-with-me" as *u8) == 1 { 3108 let n: i64 = of_sharedpage(base, azprefix, me, authed, out, cap) 3109 return of_cl_frame(out, n, cap) 3110 } 3111 if of_starts(path, "/manage/" as *u8) == 1 { 3112 let nm: *u8 = sys_mmap(64) 3113 var q: i64 = 8 3114 var t2: i64 = 0 3115 while path[q] != (0 as u8) { if t2 < 63 { nm[t2] = path[q]; t2 = t2 + 1 } q = q + 1 } 3116 nm[t2] = 0 as u8 3117 if of_name_ok(nm) == 0 { return of_err(out, "404 Not Found" as *u8, "bad name" as *u8) } 3118 let n: i64 = of_managepage(base, azprefix, me, authed, nm, tok, out, cap) 3119 if n == (0 - 1) { return of_err(out, "401 Unauthorized" as *u8, "sign in to manage sharing" as *u8) } 3120 if n == (0 - 2) { return of_err(out, "404 Not Found" as *u8, "this document has no owner (it is public)" as *u8) } 3121 if n == (0 - 3) { return of_err(out, "403 Forbidden" as *u8, "only the owner can manage sharing" as *u8) } 3122 return of_cl_frame(out, n, cap) 3123 } 3124 return of_err(out, "404 Not Found" as *u8, "no such route" as *u8) 3125} 3126 3127// ---- the offline gate body (consumed by _hdl_build/nx_office_gate) ---- 3128// D001 migration (2026-09-02): the selftest's 94 teeth all flow through this ONE ruler, so inheriting the shared 3129// verdict base is a change here and nowhere else. When a gv counter is armed (the gate arms it through 3130// of_selftest_gv) every tooth is a gv_check -- declared == executed by construction -- and the exit code carries 3131// the verdict through gv_verdict; the daemon's own `selftest` verb keeps the legacy PASS/FAIL print. 3132static g_of_gv: i64 // the armed gv counter as an address; module-level state is `static` (zero-initialised), never `var` 3133func of_ck(name: *u8, cond: i64, pass: *i64, fail: *i64) -> i64 { 3134 if g_of_gv != 0 { 3135 gv_check(name, cond, g_of_gv as *i64) 3136 if cond == 1 { pass[0] = pass[0] + 1; return 1 } 3137 fail[0] = fail[0] + 1 3138 return 0 3139 } 3140 if cond == 1 { p(" PASS " as *u8); p(name); p("\n" as *u8); pass[0] = pass[0] + 1; return 1 } 3141 p(" FAIL " as *u8); p(name); p("\n" as *u8); fail[0] = fail[0] + 1 3142 return 0 3143} 3144// the gate's entry: arm the shared counter, run every tooth through it, and let the caller emit gv_verdict LAST. 3145func of_selftest_gv(root: *u8, c: *i64) -> i64 { 3146 g_of_gv = c as i64 3147 return of_selftest(root) 3148} 3149func of_selftest(root: *u8) -> i64 { 3150 p("=== NX-OFFICE SELFTEST root=" as *u8); p(root); p(" (create/edit/version/preview/download, additive-proven, LOUD negatives) ===\n" as *u8) 3151 let base: *u8 = sys_mmap(4) 3152 base[0] = 0 as u8 3153 let pass: *i64 = sys_mmap(16) as *i64 3154 let fail: *i64 = sys_mmap(16) as *i64 3155 pass[0] = 0 3156 fail[0] = 0 3157 let out: *u8 = sys_mmap(1048576) 3158 let req: *u8 = sys_mmap(262144) 3159 let bod: *u8 = sys_mmap(131072) 3160 // T1 empty home 3161 var n: i64 = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3162 of_ck("T1 home renders" as *u8, of_memhas(out, n, "Nishi Office" as *u8), pass, fail) 3163 // helper-free POST builder: body first, then request with exact Content-Length 3164 var bo: i64 = of_cat(bod, 0, "name=family-letter&kind=doc&spec=H+Family+Letter%0AB+Dear+family%0AP+We+love+each+other." as *u8) 3165 var ro: i64 = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3166 ro = of_catn(req, ro, bo) 3167 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3168 ro = of_cat(req, ro, bod) 3169 n = of_handle(root, base, req, ro, out, 1048576) 3170 var t2ok: i64 = 0 3171 if of_memhas(out, n, "303 See Other" as *u8) == 1 { if of_memhas(out, n, "/doc/family-letter" as *u8) == 1 { t2ok = 1 } } 3172 of_ck("T2 create doc v1 (303 redirect)" as *u8, t2ok, pass, fail) 3173 let fb: *u8 = sys_mmap(1048576) 3174 let ap: *u8 = sys_mmap(600) 3175 var ao: i64 = of_cat(ap, 0, root); ao = of_cat(ap, ao, "/family-letter/v1/file.docx" as *u8); ap[ao] = 0 as u8 3176 let fl1: i64 = of_read_file(ap, fb, 1048576) 3177 var t2b: i64 = 0 3178 if fl1 > 200 { t2b = 1 } 3179 of_ck("T2b v1 .docx built on disk" as *u8, t2b, pass, fail) 3180 let pp: *u8 = sys_mmap(600) 3181 var po: i64 = of_cat(pp, 0, root); po = of_cat(pp, po, "/family-letter/v1/preview.html" as *u8); pp[po] = 0 as u8 3182 let pv: *u8 = sys_mmap(1048576) 3183 let pl: i64 = of_read_file(pp, pv, 1048576) 3184 var t2c: i64 = 0 3185 if pl > 0 { t2c = of_memhas(pv, pl, "Family Letter" as *u8) } 3186 of_ck("T2c v1 preview renders the heading" as *u8, t2c, pass, fail) 3187 // T3 doc page round-trips the spec into the editor 3188 n = of_handle(root, base, "GET /doc/family-letter HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3189 var t3: i64 = 0 3190 if of_memhas(out, n, "H Family Letter" as *u8) == 1 { if of_memhas(out, n, "Save as v2" as *u8) == 1 { t3 = 1 } } 3191 of_ck("T3 editor page carries latest spec (raw fallback)" as *u8, t3, pass, fail) 3192 // T3b VISUAL editor: doc spec rendered as editable blocks (#ed, <h2>, <b>) + app.js wired 3193 var t3b: i64 = 0 3194 if of_memhas(out, n, "id='ed' class='visual doc' contenteditable" as *u8) == 1 { 3195 if of_memhas(out, n, "<h2>Family Letter</h2>" as *u8) == 1 { 3196 if of_memhas(out, n, "<p data-k='B'><b>Dear family</b></p>" as *u8) == 1 { 3197 if of_memhas(out, n, "/app.js'></script>" as *u8) == 1 { t3b = 1 } } } } 3198 of_ck("T3b doc renders editable blocks (#ed h2/b) + app.js" as *u8, t3b, pass, fail) 3199 // T3c the client is served at /app.js as javascript 3200 var na: i64 = of_handle(root, base, "GET /app.js HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 44, out, 1048576) 3201 var t3c: i64 = 0 3202 if of_memhas(out, na, "Content-Type: application/javascript" as *u8) == 1 { if of_memhas(out, na, "getElementById" as *u8) == 1 { t3c = 1 } } 3203 of_ck("T3c /app.js serves the client as javascript" as *u8, t3c, pass, fail) 3204 // snapshot v1 spec bytes for the additive proof 3205 let s1p: *u8 = sys_mmap(600) 3206 var s1o: i64 = of_cat(s1p, 0, root); s1o = of_cat(s1p, s1o, "/family-letter/v1/spec.txt" as *u8); s1p[s1o] = 0 as u8 3207 let s1a: *u8 = sys_mmap(131072) 3208 let s1n: i64 = of_read_file(s1p, s1a, 131072) 3209 // T4 save v2 (edited) 3210 bo = of_cat(bod, 0, "name=family-letter&kind=doc&spec=H+Family+Letter+EDITED%0AP+Now+with+a+second+version." as *u8) 3211 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3212 ro = of_catn(req, ro, bo) 3213 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3214 ro = of_cat(req, ro, bod) 3215 n = of_handle(root, base, req, ro, out, 1048576) 3216 let s2p: *u8 = sys_mmap(600) 3217 var s2o: i64 = of_cat(s2p, 0, root); s2o = of_cat(s2p, s2o, "/family-letter/v2/spec.txt" as *u8); s2p[s2o] = 0 as u8 3218 let s2a: *u8 = sys_mmap(131072) 3219 let s2n: i64 = of_read_file(s2p, s2a, 131072) 3220 var t4: i64 = 0 3221 if of_memhas(out, n, "303" as *u8) == 1 { if s2n > 0 { t4 = 1 } } 3222 of_ck("T4 save again creates v2" as *u8, t4, pass, fail) 3223 let s1b: *u8 = sys_mmap(131072) 3224 let s1n2: i64 = of_read_file(s1p, s1b, 131072) 3225 var addv: i64 = 0 3226 if s1n2 == s1n { if s1n > 0 { 3227 addv = 1 3228 var ci: i64 = 0 3229 while ci < s1n { if s1a[ci] != s1b[ci] { addv = 0; ci = s1n } ci = ci + 1 } 3230 } } 3231 of_ck("T4b ADDITIVE: v1 spec bytes unchanged after v2" as *u8, addv, pass, fail) 3232 // T5 artifact download: response body == on-disk v2 bytes 3233 n = of_handle(root, base, "GET /file/family-letter/v2 HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 60, out, 1048576) 3234 var bs: i64 = 0 - 1 3235 var bi: i64 = 0 3236 while bi + 3 < n { 3237 if out[bi] == (13 as u8) { if out[bi+1] == (10 as u8) { if out[bi+2] == (13 as u8) { if out[bi+3] == (10 as u8) { bs = bi + 4; bi = n } } } } 3238 bi = bi + 1 3239 } 3240 var a2o2: i64 = of_cat(ap, 0, root) 3241 a2o2 = of_cat(ap, a2o2, "/family-letter/v2/file.docx" as *u8) 3242 ap[a2o2] = 0 as u8 3243 let fl2: i64 = of_read_file(ap, fb, 1048576) 3244 var t5: i64 = 0 3245 if bs > 0 { if n - bs == fl2 { if fl2 > 0 { 3246 t5 = 1 3247 var di: i64 = 0 3248 while di < fl2 { if out[bs + di] != fb[di] { t5 = 0; di = fl2 } di = di + 1 } 3249 } } } 3250 var t5h: i64 = of_memhas(out, bs, "wordprocessingml" as *u8) 3251 var t5ok: i64 = 0 3252 if t5 == 1 { if t5h == 1 { t5ok = 1 } } 3253 of_ck("T5 download == on-disk bytes + docx content-type" as *u8, t5ok, pass, fail) 3254 // T6 sheet with a real formula: preview shows the COMPUTED 30 3255 bo = of_cat(bod, 0, "name=family-budget&kind=sheet&spec=Item%09Cost%0AApples%0910%0APears%0920%0ATotal%09=SUM(B2:B3)" as *u8) 3256 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3257 ro = of_catn(req, ro, bo) 3258 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3259 ro = of_cat(req, ro, bod) 3260 n = of_handle(root, base, req, ro, out, 1048576) 3261 var t6r: i64 = of_memhas(out, n, "303" as *u8) 3262 n = of_handle(root, base, "GET /preview/family-budget/v1 HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 63, out, 1048576) 3263 var t6: i64 = 0 3264 if t6r == 1 { if of_memhas(out, n, "30" as *u8) == 1 { t6 = 1 } } 3265 of_ck("T6 sheet formula computed in preview (SUM=30)" as *u8, t6, pass, fail) 3266 // T7 deck 3267 bo = of_cat(bod, 0, "name=reunion-deck&kind=deck&spec=S+Reunion+2026%0AB+Where:+the+lake%0AS+Food%0AB+Friday:+burgers" as *u8) 3268 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3269 ro = of_catn(req, ro, bo) 3270 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3271 ro = of_cat(req, ro, bod) 3272 n = of_handle(root, base, req, ro, out, 1048576) 3273 var t7r: i64 = of_memhas(out, n, "303" as *u8) 3274 n = of_handle(root, base, "GET /preview/reunion-deck/v1 HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 62, out, 1048576) 3275 var t7: i64 = 0 3276 if t7r == 1 { if of_memhas(out, n, "Reunion 2026" as *u8) == 1 { t7 = 1 } } 3277 of_ck("T7 deck builds + preview shows slide title" as *u8, t7, pass, fail) 3278 // T7b VISUAL editors for sheet + deck (editable grid #grid, editable slides #deck) 3279 n = of_handle(root, base, "GET /doc/family-budget HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3280 var t7b: i64 = 0 3281 if of_memhas(out, n, "id='grid' class='visual sheet'" as *u8) == 1 { if of_memhas(out, n, "<td contenteditable='true'>Apples</td>" as *u8) == 1 { t7b = 1 } } 3282 of_ck("T7b sheet renders an editable grid (#grid cells)" as *u8, t7b, pass, fail) 3283 n = of_handle(root, base, "GET /doc/reunion-deck HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 55, out, 1048576) 3284 var t7c: i64 = 0 3285 if of_memhas(out, n, "id='deck' class='visual deck'" as *u8) == 1 { if of_memhas(out, n, "<h3 contenteditable='true'>Reunion 2026</h3>" as *u8) == 1 { if of_memhas(out, n, "data-act='slide'" as *u8) == 1 { t7c = 1 } } } 3286 of_ck("T7c deck renders editable slides (#deck h3 + toolbar)" as *u8, t7c, pass, fail) 3287 // T8 LOUD negatives 3288 bo = of_cat(bod, 0, "name=Bad/Name&kind=doc&spec=P+x" as *u8) 3289 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3290 ro = of_catn(req, ro, bo) 3291 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3292 ro = of_cat(req, ro, bod) 3293 n = of_handle(root, base, req, ro, out, 1048576) 3294 of_ck("T8a bad name refused 400" as *u8, of_memhas(out, n, "400" as *u8), pass, fail) 3295 bo = of_cat(bod, 0, "name=family-letter&kind=sheet&spec=A%09B" as *u8) 3296 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3297 ro = of_catn(req, ro, bo) 3298 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3299 ro = of_cat(req, ro, bod) 3300 n = of_handle(root, base, req, ro, out, 1048576) 3301 of_ck("T8b kind flip on existing name refused 400" as *u8, of_memhas(out, n, "kind mismatch" as *u8), pass, fail) 3302 n = of_handle(root, base, "GET /file/family-letter/v9 HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 60, out, 1048576) 3303 of_ck("T8c missing version 404" as *u8, of_memhas(out, n, "404" as *u8), pass, fail) 3304 bo = of_cat(bod, 0, "name=family-letter&kind=doc&spec=P+evil" as *u8) 3305 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nOrigin: http://evil.example\r\nContent-Length: " as *u8) 3306 ro = of_catn(req, ro, bo) 3307 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3308 ro = of_cat(req, ro, bod) 3309 n = of_handle(root, base, req, ro, out, 1048576) 3310 of_ck("T8d cross-origin POST refused 403" as *u8, of_memhas(out, n, "403" as *u8), pass, fail) 3311 let kb: *u8 = sys_mmap(64) 3312 var t8e: i64 = 0 3313 if of_manifest_count(root, "family-letter" as *u8, kb, 64) == 2 { t8e = 1 } 3314 of_ck("T8e negatives left NO new versions (still 2)" as *u8, t8e, pass, fail) 3315 // T9 home lists all three 3316 n = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3317 var t9: i64 = 0 3318 if of_memhas(out, n, "family-letter" as *u8) == 1 { if of_memhas(out, n, "family-budget" as *u8) == 1 { if of_memhas(out, n, "reunion-deck" as *u8) == 1 { t9 = 1 } } } 3319 of_ck("T9 home lists all three files" as *u8, t9, pass, fail) 3320 // T10 MOUNTED at /office: the edge forwards the full path; stripping routes it, links carry the prefix. 3321 let mbase: *u8 = "/office" as *u8 3322 n = of_handle(root, mbase, "GET /office HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" as *u8, 46, out, 1048576) 3323 var t10a: i64 = 0 3324 if of_memhas(out, n, "Nishi Office" as *u8) == 1 { if of_memhas(out, n, "/office/doc/family-letter" as *u8) == 1 { t10a = 1 } } 3325 of_ck("T10a /office home renders + links carry the mount prefix" as *u8, t10a, pass, fail) 3326 n = of_handle(root, mbase, "GET /office/file/family-letter/v2 HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" as *u8, 68, out, 1048576) 3327 var t10b: i64 = 0 3328 if of_memhas(out, n, "200 OK" as *u8) == 1 { if of_memhas(out, n, "wordprocessingml" as *u8) == 1 { t10b = 1 } } 3329 of_ck("T10b /office/file/.../v2 downloads through the mount" as *u8, t10b, pass, fail) 3330 // T10c a query string (cache-bust, browser params) must not break routing -> home still renders 3331 n = of_handle(root, mbase, "GET /office?v=golive9f2 HTTP/1.1\r\nHost: nishifamily.com\r\n\r\n" as *u8, 58, out, 1048576) 3332 of_ck("T10c /office?query still routes to home (no 404)" as *u8, of_memhas(out, n, "Nishi Office" as *u8), pass, fail) 3333 // T11 VERSION DIFF: controlled v1/v2 with a partial overlap -> LCS keeps 2, adds 1, removes 1. 3334 // NOTE: of_cat does NOT NUL-terminate -> terminate bod at bo so of_cat(req,ro,bod) copies EXACTLY the body 3335 // (else a shorter body trails leftover bytes from a longer prior test = spec contamination). 3336 bo = of_cat(bod, 0, "name=diffdoc&kind=doc&spec=H+Title%0AP+Line+A%0AP+Line+B" as *u8); bod[bo] = 0 as u8 3337 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3338 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3339 n = of_handle(root, base, req, ro, out, 1048576) 3340 bo = of_cat(bod, 0, "name=diffdoc&kind=doc&spec=H+Title%0AP+Line+A+CHANGED%0AP+Line+B" as *u8); bod[bo] = 0 as u8 3341 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3342 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3343 n = of_handle(root, base, req, ro, out, 1048576) 3344 n = of_handle(root, base, "GET /diff/diffdoc/1/2 HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 53, out, 1048576) 3345 var t11: i64 = 0 3346 if of_memhas(out, n, "Changes: v1 &rarr; v2" as *u8) == 1 { 3347 if of_memhas(out, n, "class='ddel'>&minus;&nbsp;P Line A</div>" as *u8) == 1 { 3348 if of_memhas(out, n, "class='dadd'>+&nbsp;P Line A CHANGED</div>" as *u8) == 1 { 3349 if of_memhas(out, n, "class='dkeep'>&nbsp;&nbsp;H Title</div>" as *u8) == 1 { 3350 if of_memhas(out, n, "<b>1</b> line(s) added, <b>1</b> removed" as *u8) == 1 { t11 = 1 } } } } } 3351 of_ck("T11 version diff: LCS keep/add/del + counts (1 added, 1 removed)" as *u8, t11, pass, fail) 3352 // T11b the doc page links the diff for v>=2 3353 n = of_handle(root, base, "GET /doc/diffdoc HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 50, out, 1048576) 3354 of_ck("T11b doc page links 'vs v1' diff for v2" as *u8, of_memhas(out, n, "/diff/diffdoc/1/2'>vs v1" as *u8), pass, fail) 3355 // T11c doc page offers a Restore button for the older version (v1), not for the current (v2) 3356 of_ck("T11c versions table has a Restore form for v1" as *u8, of_memhas(out, n, "/restore' style='margin:0'><input type='hidden' name='name' value='diffdoc'><input type='hidden' name='version' value='1'" as *u8), pass, fail) 3357 // T11d RESTORE: put diffdoc v1 back -> creates v3 == v1 spec, ADDITIVE (v1 + v2 untouched) 3358 bo = of_cat(bod, 0, "name=diffdoc&version=1" as *u8); bod[bo] = 0 as u8 3359 ro = of_cat(req, 0, "POST /restore HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3360 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3361 n = of_handle(root, base, req, ro, out, 1048576) 3362 var t11d: i64 = of_memhas(out, n, "303" as *u8) 3363 // v3 spec must byte-equal v1 spec; manifest now has 3 versions 3364 let rkbx: *u8 = sys_mmap(64) 3365 let rvcx: i64 = of_manifest_count(root, "diffdoc" as *u8, rkbx, 64) 3366 let s1x: *u8 = sys_mmap(4096) 3367 let s3x: *u8 = sys_mmap(4096) 3368 let n1x: i64 = of_read_version_spec(root, "diffdoc" as *u8, 1, s1x, 4095) 3369 let n3x: i64 = of_read_version_spec(root, "diffdoc" as *u8, 3, s3x, 4095) 3370 var eqx: i64 = 0 3371 if rvcx == 3 { if n1x == n3x { if n1x > 0 { 3372 eqx = 1 3373 var ci: i64 = 0 3374 while ci < n1x { if s1x[ci] != s3x[ci] { eqx = 0; ci = n1x } ci = ci + 1 } 3375 } } } 3376 var t11dok: i64 = 0 3377 if t11d == 1 { if eqx == 1 { t11dok = 1 } } 3378 of_ck("T11d restore v1 -> v3==v1 spec, additive (now 3 versions)" as *u8, t11dok, pass, fail) 3379 // T12 the PRODUCT SHELL (U-axes rung): search / type chips / sort order / REAL thumbnails / empty states / 3380 // editor chrome. Ordering asserted with of_findpos, not just presence. 3381 n = of_handle(root, base, "GET /?q=budget HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 47, out, 1048576) 3382 var t12a: i64 = 0 3383 if of_memhas(out, n, "family-budget" as *u8) == 1 { if of_memhas(out, n, "/doc/family-letter" as *u8) == 0 { t12a = 1 } } 3384 of_ck("T12a search q=budget filters the card grid" as *u8, t12a, pass, fail) 3385 n = of_handle(root, base, "GET /?type=deck HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 48, out, 1048576) 3386 var t12b: i64 = 0 3387 if of_memhas(out, n, "reunion-deck" as *u8) == 1 { if of_memhas(out, n, "/doc/family-budget" as *u8) == 0 { t12b = 1 } } 3388 of_ck("T12b type=deck chip filters to decks only" as *u8, t12b, pass, fail) 3389 n = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3390 var pd: i64 = of_findpos(out, n, "/doc/reunion-deck" as *u8) 3391 var plt: i64 = of_findpos(out, n, "/doc/family-letter" as *u8) 3392 var t12c: i64 = 0 3393 if pd >= 0 { if plt >= 0 { if pd < plt { t12c = 1 } } } 3394 of_ck("T12c default sort = recently edited first (deck before letter)" as *u8, t12c, pass, fail) 3395 n = of_handle(root, base, "GET /?sort=name HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 48, out, 1048576) 3396 var pb2: i64 = of_findpos(out, n, "/doc/family-budget" as *u8) 3397 var pl2: i64 = of_findpos(out, n, "/doc/family-letter" as *u8) 3398 var pd2: i64 = of_findpos(out, n, "/doc/reunion-deck" as *u8) 3399 var t12d: i64 = 0 3400 if pb2 >= 0 { if pl2 > pb2 { if pd2 > pl2 { t12d = 1 } } } 3401 of_ck("T12d sort=name orders the grid alphabetically" as *u8, t12d, pass, fail) 3402 n = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3403 var t12e: i64 = 0 3404 if of_memhas(out, n, "class='thumb'" as *u8) == 1 { if of_memhas(out, n, "tsheet" as *u8) == 1 { if of_memhas(out, n, "Apples" as *u8) == 1 { if of_memhas(out, n, "Family Letter EDITED" as *u8) == 1 { t12e = 1 } } } } 3405 of_ck("T12e home cards carry REAL content thumbnails (sheet cells + doc heading)" as *u8, t12e, pass, fail) 3406 n = of_handle(root, base, "GET /?q=zzzz HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 45, out, 1048576) 3407 of_ck("T12f no-match search shows an empty state" as *u8, of_memhas(out, n, "No files match" as *u8), pass, fail) 3408 let root2: *u8 = sys_mmap(600) 3409 var r2o: i64 = of_cat(root2, 0, root); r2o = of_cat(root2, r2o, "-fresh" as *u8); root2[r2o] = 0 as u8 3410 n = of_handle(root2, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3411 of_ck("T12g first-run onboarding empty state" as *u8, of_memhas(out, n, "Create your first document" as *u8), pass, fail) 3412 n = of_handle(root, base, "GET /doc/family-letter HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3413 var t12h: i64 = 0 3414 if of_memhas(out, n, "Saved v2" as *u8) == 1 { if of_memhas(out, n, "data-act='u'" as *u8) == 1 { if of_memhas(out, n, "data-act='find'" as *u8) == 1 { if of_memhas(out, n, "id='savest'" as *u8) == 1 { t12h = 1 } } } } 3415 of_ck("T12h editor carries saved-stamp + undo/find controls + save-state slot" as *u8, t12h, pass, fail) 3416 var nj: i64 = of_handle(root, base, "GET /app.js HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 44, out, 1048576) 3417 var t12i: i64 = 0 3418 if of_memhas(out, nj, "ctrlKey" as *u8) == 1 { if of_memhas(out, nj, "createTreeWalker" as *u8) == 1 { if of_memhas(out, nj, "localStorage" as *u8) == 1 { t12i = 1 } } } 3419 of_ck("T12i app.js ships find/shortcuts/theme (ctrlKey+TreeWalker+localStorage)" as *u8, t12i, pass, fail) 3420 // T13 TRUE AUTOSAVE (U4 rung): ajax=1 -> 200 OK v<N> (no 303 navigation), manifest tags the version with 3421 // the additive 4th field "auto", and the Versions table labels it. The JS side (debounce + changed-only) 3422 // ships in app.js (T13d needles) -- browser timing itself is not headless-executed here (honest caveat). 3423 bo = of_cat(bod, 0, "name=family-letter&kind=doc&spec=H+Family+Letter+AUTO%0AP+Background+save.&ajax=1" as *u8) 3424 bod[bo] = 0 as u8 3425 ro = of_cat(req, 0, "POST /save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3426 ro = of_catn(req, ro, bo) 3427 ro = of_cat(req, ro, "\r\n\r\n" as *u8) 3428 ro = of_cat(req, ro, bod) 3429 n = of_handle(root, base, req, ro, out, 1048576) 3430 var t13a: i64 = 0 3431 if of_memhas(out, n, "200 OK" as *u8) == 1 { if of_memhas(out, n, "OK v3" as *u8) == 1 { if of_memhas(out, n, "303" as *u8) == 0 { t13a = 1 } } } 3432 of_ck("T13a ajax autosave answers 200 OK v3 (no 303)" as *u8, t13a, pass, fail) 3433 var t13b: i64 = 0 3434 if of_manifest_is_auto(root, "family-letter" as *u8, 3) == 1 { if of_manifest_is_auto(root, "family-letter" as *u8, 2) == 0 { t13b = 1 } } 3435 of_ck("T13b manifest tags v3 auto, v2 not" as *u8, t13b, pass, fail) 3436 n = of_handle(root, base, "GET /doc/family-letter HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3437 var t13c: i64 = 0 3438 if of_memhas(out, n, "(auto)" as *u8) == 1 { if of_memhas(out, n, "Save as v4" as *u8) == 1 { t13c = 1 } } 3439 of_ck("T13c versions table labels the autosave + next save renumbers v4" as *u8, t13c, pass, fail) 3440 var nj2: i64 = of_handle(root, base, "GET /app.js HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 44, out, 1048576) 3441 var t13d: i64 = 0 3442 if of_memhas(out, nj2, "ajax=1" as *u8) == 1 { if of_memhas(out, nj2, "lastSpec" as *u8) == 1 { if of_memhas(out, nj2, "Autosaved v" as *u8) == 1 { t13d = 1 } } } 3443 of_ck("T13d app.js ships the autosave engine (ajax=1 + changed-only lastSpec)" as *u8, t13d, pass, fail) 3444 // T14 HTML pages carry Content-Length so the STRICT sovereign browser can frame them (the /office in-browser 3445 // fetch failed without it). Assert present on the home response AND that its value == the actual body length. 3446 n = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3447 var t14: i64 = 0 3448 if of_memhas(out, n, "Content-Length: " as *u8) == 1 { 3449 var hp: i64 = 0 - 1 3450 var xi: i64 = 0 3451 while xi + 3 < n { if out[xi] == (13 as u8) { if out[xi+1] == (10 as u8) { if out[xi+2] == (13 as u8) { if out[xi+3] == (10 as u8) { hp = xi; xi = n } } } } xi = xi + 1 } 3452 if hp >= 0 { 3453 let bodylen: i64 = n - (hp + 4) 3454 var cl: i64 = 0 3455 var found: i64 = 0 3456 var ci: i64 = 0 3457 let key: *u8 = "Content-Length: " as *u8 3458 while ci + 16 < hp { 3459 if of_starts((out as i64 + ci) as *u8, key) == 1 { 3460 var t: i64 = ci + 16 3461 while t < hp { let dch: i64 = out[t] as i64; if dch >= 48 { if dch <= 57 { cl = cl * 10 + (dch - 48); found = 1 } } if out[t] == (13 as u8) { t = hp } else { t = t + 1 } } 3462 ci = hp 3463 } else { ci = ci + 1 } 3464 } 3465 if found == 1 { if cl == bodylen { t14 = 1 } } 3466 } 3467 } 3468 of_ck("T14 home carries a CORRECT Content-Length (strict-client framable)" as *u8, t14, pass, fail) 3469 3470 // ---- AUTHZ (nx_rebac): owner-binding + read/write gating + share/unshare -- the office integration ---- 3471 let azp: *u8 = sys_mmap(96); var azo: i64 = of_cat(azp, 0, "/tmp/ofauthz_" as *u8); azo = of_catn(azp, azo, sys_now_us()); azo = of_cat(azp, azo, "_" as *u8); azp[azo] = 0 as u8 3472 let azal: *u8 = sys_mmap(24); of_meref(azal, "alice" as *u8) 3473 let azbo: *u8 = sys_mmap(24); of_meref(azbo, "bob" as *u8) 3474 let azca: *u8 = sys_mmap(24); of_meref(azca, "carol" as *u8) 3475 let azempty: *u8 = sys_mmap(4); azempty[0] = 0 as u8 3476 of_ck("AZ0a unowned doc PUBLIC to authed (non-breaking)" as *u8, of_read_ok(azp, azal, 1, "flyer" as *u8), pass, fail) 3477 of_ck("AZ0b unowned doc PUBLIC to anon (non-breaking)" as *u8, of_read_ok(azp, azempty, 0, "flyer" as *u8), pass, fail) 3478 let azsref: *u8 = sys_mmap(32); of_docref(azsref, "secret" as *u8) 3479 rb_put(azp, azsref, "owner" as *u8, azal, "alice" as *u8, 1) 3480 of_ck("AZ1 owner alice reads owned secret" as *u8, of_read_ok(azp, azal, 1, "secret" as *u8), pass, fail) 3481 of_ck("AZ2 anon DENIED on owned secret" as *u8, 1 - of_read_ok(azp, azempty, 0, "secret" as *u8), pass, fail) 3482 of_ck("AZ3 bob (no grant) DENIED read" as *u8, 1 - of_read_ok(azp, azbo, 1, "secret" as *u8), pass, fail) 3483 of_ck("AZ4 bob DENIED write" as *u8, 1 - of_write_ok(azp, azbo, 1, "secret" as *u8), pass, fail) 3484 rb_put(azp, azsref, "viewer" as *u8, azbo, "alice" as *u8, 1) 3485 of_ck("AZ5 bob now READS (shared viewer)" as *u8, of_read_ok(azp, azbo, 1, "secret" as *u8), pass, fail) 3486 of_ck("AZ6 bob viewer still cannot WRITE" as *u8, 1 - of_write_ok(azp, azbo, 1, "secret" as *u8), pass, fail) 3487 rb_put(azp, azsref, "editor" as *u8, azca, "alice" as *u8, 1) 3488 of_ck("AZ7 carol editor CAN write" as *u8, of_write_ok(azp, azca, 1, "secret" as *u8), pass, fail) 3489 rb_put(azp, azsref, "viewer" as *u8, azbo, "alice" as *u8, 0) 3490 of_ck("AZ8 bob REVOKED (unshare tombstone)" as *u8, 1 - of_read_ok(azp, azbo, 1, "secret" as *u8), pass, fail) 3491 of_ck("AZ9 alice may_grant (owner)" as *u8, rb_may_grant(azp, azal, azsref), pass, fail) 3492 of_ck("AZ10 bob may_grant DENIED (not owner)" as *u8, 1 - rb_may_grant(azp, azbo, azsref), pass, fail) 3493 let azdob: *u8 = sys_mmap(8192) 3494 let azsh1: *u8 = "name=secret&who=dan&level=viewer" as *u8 3495 let azr1: i64 = of_do_share("/office" as *u8, azp, azal, "alice" as *u8, 1, azsh1, of_slen(azsh1), azdob, 1) 3496 let azdan: *u8 = sys_mmap(16); of_meref(azdan, "dan" as *u8) 3497 of_ck("AZ11a of_do_share owner->dan = 303" as *u8, of_memhas(azdob, azr1, "303" as *u8), pass, fail) 3498 of_ck("AZ11b dan now reads secret" as *u8, of_read_ok(azp, azdan, 1, "secret" as *u8), pass, fail) 3499 let azr2: i64 = of_do_share("/office" as *u8, azp, azbo, "bob" as *u8, 1, azsh1, of_slen(azsh1), azdob, 1) 3500 of_ck("AZ12 of_do_share by non-owner bob = 403" as *u8, of_memhas(azdob, azr2, "403" as *u8), pass, fail) 3501 let azsh2: *u8 = "name=secret&who=ev:il&level=viewer" as *u8 3502 let azr3: i64 = of_do_share("/office" as *u8, azp, azal, "alice" as *u8, 1, azsh2, of_slen(azsh2), azdob, 1) 3503 of_ck("AZ13 of_do_share bad handle = 400 (no forge)" as *u8, of_memhas(azdob, azr3, "400" as *u8), pass, fail) 3504 let azmob: *u8 = sys_mmap(65536) 3505 let azm1: i64 = of_managepage("/office" as *u8, azp, azal, 1, "secret" as *u8, "TOK" as *u8, azmob, 65536) 3506 of_ck("AZ14 owner manage page renders" as *u8, of_memhas(azmob, azm1, "Sharing: secret" as *u8), pass, fail) 3507 let azm2: i64 = of_managepage("/office" as *u8, azp, azbo, 1, "secret" as *u8, "TOK" as *u8, azmob, 65536) 3508 var azm2ok: i64 = 0 3509 if azm2 == (0 - 3) { azm2ok = 1 } 3510 of_ck("AZ15 non-owner manage DENIED (-3)" as *u8, azm2ok, pass, fail) 3511 let azm3: i64 = of_managepage("/office" as *u8, azp, azal, 1, "flyer" as *u8, "TOK" as *u8, azmob, 65536) 3512 var azm3ok: i64 = 0 3513 if azm3 == (0 - 2) { azm3ok = 1 } 3514 of_ck("AZ16 manage unowned = not-owned (-2)" as *u8, azm3ok, pass, fail) 3515 of_ck("AZ17 handle validator rejects colon (no type forge)" as *u8, 1 - of_tok_ok("ev:il" as *u8), pass, fail) 3516 of_ck("AZ18 handle validator accepts ok_h-1" as *u8, of_tok_ok("ok_h-1" as *u8), pass, fail) 3517 3518 // ---- GROUP SHARING (the userset differentiator): share a doc with a GROUP, members inherit access ---- 3519 let azgadd: *u8 = "group=team&who=rose" as *u8 3520 let azgr: i64 = of_do_group("/office" as *u8, azp, azal, "alice" as *u8, 1, azgadd, of_slen(azgadd), azdob, 1) 3521 of_ck("AZ19 alice creates group team + adds rose = 303" as *u8, of_memhas(azdob, azgr, "303" as *u8), pass, fail) 3522 let azgshare: *u8 = "name=secret&who=team&level=viewer&target=group" as *u8 3523 let azgs: i64 = of_do_share("/office" as *u8, azp, azal, "alice" as *u8, 1, azgshare, of_slen(azgshare), azdob, 1) 3524 of_ck("AZ20 share secret with GROUP team = 303" as *u8, of_memhas(azdob, azgs, "303" as *u8), pass, fail) 3525 let azrose: *u8 = sys_mmap(16); of_meref(azrose, "rose" as *u8) 3526 of_ck("AZ21 rose reads secret VIA GROUP membership (userset)" as *u8, of_read_ok(azp, azrose, 1, "secret" as *u8), pass, fail) 3527 // reverse index (list-objects): what docs can each subject reach? 3528 let azmd: *i64 = sys_mmap(8 * 128) as *i64 3529 let aznd: i64 = of_my_docs(azp, azrose, azmd, 128) 3530 of_ck("AZ21b reverse-index: rose's docs include secret VIA GROUP" as *u8, rb_in_list(azmd, aznd, "doc:secret" as *u8), pass, fail) 3531 let azmd2: *i64 = sys_mmap(8 * 128) as *i64 3532 let aznd2: i64 = of_my_docs(azp, azal, azmd2, 128) 3533 of_ck("AZ21c reverse-index: alice's docs include her owned secret" as *u8, rb_in_list(azmd2, aznd2, "doc:secret" as *u8), pass, fail) 3534 let azfrank: *u8 = sys_mmap(16); of_meref(azfrank, "frank" as *u8) 3535 of_ck("AZ22 frank (not in team) DENIED" as *u8, 1 - of_read_ok(azp, azfrank, 1, "secret" as *u8), pass, fail) 3536 let azgrem: *u8 = "group=team&who=rose" as *u8 3537 of_do_group("/office" as *u8, azp, azal, "alice" as *u8, 1, azgrem, of_slen(azgrem), azdob, 0) 3538 of_ck("AZ23 remove rose from team -> loses secret (userset re-eval)" as *u8, 1 - of_read_ok(azp, azrose, 1, "secret" as *u8), pass, fail) 3539 let azbob2: *u8 = "group=team&who=x" as *u8 3540 let azgb: i64 = of_do_group("/office" as *u8, azp, azbo, "bob" as *u8, 1, azbob2, of_slen(azbob2), azdob, 1) 3541 of_ck("AZ24 non-owner bob cannot add to team = 403 (no group hijack)" as *u8, of_memhas(azdob, azgb, "403" as *u8), pass, fail) 3542 3543 // ---- AI CONTINUE (in-app AI over our own 0.5B seat): offline gate proves the button + graceful 503 ---- 3544 // T-AI-a: the doc editor page offers the "Continue with AI" form (doc kind). 3545 n = of_handle(root, base, "GET /doc/family-letter HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3546 var tai_a: i64 = 0 3547 if of_memhas(out, n, "Continue with AI" as *u8) == 1 { if of_memhas(out, n, "/ai'><input type='hidden' name='name' value='family-letter'" as *u8) == 1 { tai_a = 1 } } 3548 of_ck("T-AI-a doc page offers the AI-continue form (our own 0.5B model)" as *u8, tai_a, pass, fail) 3549 // T-AI-b: POST /office/ai with the LLM seat DOWN (offline gate) -> graceful 503, no version created, no crash. 3550 let aicnt0: *u8 = sys_mmap(64) 3551 let aiv0: i64 = of_manifest_count(root, "family-letter" as *u8, aicnt0, 64) 3552 bo = of_cat(bod, 0, "name=family-letter" as *u8); bod[bo] = 0 as u8 3553 ro = of_cat(req, 0, "POST /office/ai HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3554 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3555 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3556 let aicnt1: *u8 = sys_mmap(64) 3557 let aiv1: i64 = of_manifest_count(root, "family-letter" as *u8, aicnt1, 64) 3558 // A FIXTURE MUST ASSERT ITS OWN PRECONDITION (measured 2026-09-02): this tooth ASSUMED the seat at 3559 // 127.0.0.1:11434 was DOWN, and the day the estate's sovereign LLM seat came up on the NAS the 3560 // capability WORKED (200, one new version) and the gate read the working feature as a failure -- 3561 // office went RED on 93/94 with nothing wrong. The seat's state is PROBED, and each state carries its 3562 // own contract: DOWN -> graceful 503 and NO version; UP -> a completion and EXACTLY ONE new version. 3563 // Neither arm is vacuous: the probe result is the fixture reaching its condition, printed by name. 3564 let seat_addr: *u8 = sys_mmap(16) 3565 nx_http_client_sockaddr_ipv4(seat_addr, 127, 0, 0, 1, 11434) 3566 var seat_up: i64 = 0 3567 let seat_fd: i64 = sys_socket(2, 1, 0) 3568 if seat_fd >= 0 { if sys_connect(seat_fd, seat_addr, 16) >= 0 { seat_up = 1 } sys_close(seat_fd) } 3569 var tai_b: i64 = 0 3570 if seat_up == 0 { 3571 if of_memhas(out, n, "503" as *u8) == 1 { if aiv1 == aiv0 { tai_b = 1 } } 3572 of_ck("T-AI-b POST /ai with seat DOWN (probed: refused) -> graceful 503 (framed) + NO version created" as *u8, tai_b, pass, fail) 3573 } else { 3574 // the seat answered the connect; whether it answered the PROMPT inside the handler's budget is the seat's 3575 // load, not the office's contract (measured 2026-09-02: the same binary passed under the ship's prove and 3576 // failed under the referee a minute later, the seat busy). The office's contract is: a completion becomes 3577 // EXACTLY ONE version, and a missing completion becomes a framed 503 with NO version -- never a half-write, 3578 // never a lost answer. Both outcomes are named so the referee row carries the state it measured. 3579 if of_memhas(out, n, "503" as *u8) == 0 { 3580 if aiv1 == aiv0 + 1 { tai_b = 1 } 3581 of_ck("T-AI-b POST /ai with seat UP (probed: connected, answered) -> the completion landed as EXACTLY ONE new version" as *u8, tai_b, pass, fail) 3582 } else { 3583 if aiv1 == aiv0 { tai_b = 1 } 3584 of_ck("T-AI-b POST /ai with seat UP (probed: connected, NO completion inside the handler budget) -> framed 503 + NO version created" as *u8, tai_b, pass, fail) 3585 } 3586 } 3587 // ---- U4 OFFLINE/PWA + SKELETONS + A11Y ---- 3588 // T-U4-a: the web app manifest is served and installable (name + start_url). 3589 n = of_handle(root, base, "GET /manifest.webmanifest HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 59, out, 1048576) 3590 var tu4_a: i64 = 0 3591 if of_memhas(out, n, "200 OK" as *u8) == 1 { if of_memhas(out, n, "Nishi Office" as *u8) == 1 { if of_memhas(out, n, "standalone" as *u8) == 1 { tu4_a = 1 } } } 3592 of_ck("T-U4-a /manifest.webmanifest serves an installable PWA manifest" as *u8, tu4_a, pass, fail) 3593 // T-U4-b: the service worker is served AT THE MOUNT with Service-Worker-Allowed, else its scope cannot 3594 // cover the app it is meant to make offline-capable. 3595 n = of_handle(root, base, "GET /sw.js HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 44, out, 1048576) 3596 var tu4_b: i64 = 0 3597 if of_memhas(out, n, "200 OK" as *u8) == 1 { if of_memhas(out, n, "Service-Worker-Allowed" as *u8) == 1 { tu4_b = 1 } } 3598 of_ck("T-U4-b /sw.js serves the worker with Service-Worker-Allowed" as *u8, tu4_b, pass, fail) 3599 // T-U4-c: the worker must NEVER cache document content -- a never-lose-versions app showing a stale doc 3600 // would be the one lie its whole design forbids. Assert the exclusion is actually in the shipped worker. 3601 let swb: *u8 = sys_mmap(65536) 3602 let swl: i64 = of_read_asset("office_sw.js" as *u8, swb, 65535) 3603 var tu4_c: i64 = 0 3604 if swl > 0 { if of_memhas(swb, swl, "/doc/" as *u8) == 1 { if of_memhas(swb, swl, ".method !== 'GET'" as *u8) == 1 { tu4_c = 1 } } } 3605 of_ck("T-U4-c the worker EXCLUDES /doc/ content and never touches a write" as *u8, tu4_c, pass, fail) 3606 // T-U4-d: shell head advertises the manifest + theme colour, and the skeleton style exists. 3607 n = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 39, out, 1048576) 3608 var tu4_d: i64 = 0 3609 if of_memhas(out, n, "rel='manifest'" as *u8) == 1 { if of_memhas(out, n, "theme-color" as *u8) == 1 { if of_memhas(out, n, ".skel{" as *u8) == 1 { tu4_d = 1 } } } 3610 of_ck("T-U4-d shell advertises the manifest + theme-color and ships skeleton styles" as *u8, tu4_d, pass, fail) 3611 // ---- U3 LIBRARY ORGANISATION: starred + folders + shared-with-me ---- 3612 // T-U3-a: star toggles ON, is visible in the library under ?filter=starred, and toggles back OFF. 3613 bo = of_cat(bod, 0, "name=family-letter" as *u8); bod[bo] = 0 as u8 3614 ro = of_cat(req, 0, "POST /office/star HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3615 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3616 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3617 var tu3_a: i64 = 0 3618 if of_starred(root, "family-letter" as *u8) == 1 { 3619 n = of_handle(root, base, "GET /?filter=starred HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 53, out, 1048576) 3620 if of_memhas(out, n, "family-letter" as *u8) == 1 { tu3_a = 1 } 3621 } 3622 of_ck("T-U3-a star ON and the starred filter shows the file" as *u8, tu3_a, pass, fail) 3623 // T-U3-b: the starred filter must EXCLUDE an unstarred file -- a filter that shows everything is not a filter. 3624 var tu3_b: i64 = 0 3625 if of_memhas(out, n, "family-budget" as *u8) == 0 { tu3_b = 1 } 3626 of_ck("T-U3-b starred filter EXCLUDES unstarred files (non-vacuous)" as *u8, tu3_b, pass, fail) 3627 // T-U3-c: folder set, then the folder filter selects it and rejects a different folder. 3628 bo = of_cat(bod, 0, "name=family-letter&folder=reunion" as *u8); bod[bo] = 0 as u8 3629 ro = of_cat(req, 0, "POST /office/folder HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3630 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3631 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3632 let fchk: *u8 = sys_mmap(64) 3633 of_folder_get(root, "family-letter" as *u8, fchk, 64) 3634 var tu3_c: i64 = 0 3635 if of_seq(fchk, "reunion" as *u8) == 1 { 3636 n = of_handle(root, base, "GET /?folder=reunion HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 53, out, 1048576) 3637 if of_memhas(out, n, "family-letter" as *u8) == 1 { if of_memhas(out, n, "family-budget" as *u8) == 0 { tu3_c = 1 } } 3638 } 3639 of_ck("T-U3-c folder set + folder filter selects only that folder" as *u8, tu3_c, pass, fail) 3640 // T-U3-d: a folder label carrying separators or markup is REFUSED (it becomes a URL filter value). 3641 bo = of_cat(bod, 0, "name=family-letter&folder=a/b" as *u8); bod[bo] = 0 as u8 3642 ro = of_cat(req, 0, "POST /office/folder HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3643 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3644 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3645 of_ck("T-U3-d a folder label with a separator is LOUDLY refused" as *u8, of_memhas(out, n, "400" as *u8), pass, fail) 3646 // T-U3-e: the doc page offers both controls. 3647 n = of_handle(root, base, "GET /doc/family-letter HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3648 var tu3_e: i64 = 0 3649 if of_memhas(out, n, "Organise" as *u8) == 1 { if of_memhas(out, n, "/star'" as *u8) == 1 { if of_memhas(out, n, "/folder'" as *u8) == 1 { tu3_e = 1 } } } 3650 of_ck("T-U3-e doc page offers star + folder controls" as *u8, tu3_e, pass, fail) 3651 // ---- TEMPLATES GALLERY (U3): real starter content, not an empty page ---- 3652 // T-TM-a: the home page offers the gallery and its templates carry WORKING content, not lorem text -- the 3653 // budget must ship a live =SUM and a #CF rule, else it demonstrates nothing about the engine underneath. 3654 n = of_handle(root, base, "GET / HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 38, out, 1048576) 3655 var ttm_a: i64 = 0 3656 if of_memhas(out, n, "<h2>Templates</h2>" as *u8) == 1 { 3657 if of_memhas(out, n, "Meeting agenda" as *u8) == 1 { 3658 if of_memhas(out, n, "Monthly budget" as *u8) == 1 { 3659 if of_memhas(out, n, "=SUM(B2:B3)" as *u8) == 1 { if of_memhas(out, n, "#CF B2:B3 greaterThan 300" as *u8) == 1 { ttm_a = 1 } } 3660 } 3661 } 3662 } 3663 of_ck("T-TM-a home offers Templates and the budget carries a REAL formula + CF rule" as *u8, ttm_a, pass, fail) 3664 // T-TM-b: a template POSTs to the SAME /save contract, so it becomes an ORDINARY versioned file. 3665 bo = of_cat(bod, 0, "name=tmpl-check&kind=doc&spec=H+Letter%0AP+Dear+friend%2C" as *u8); bod[bo] = 0 as u8 3666 ro = of_cat(req, 0, "POST /office/save HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3667 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3668 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3669 let tmk: *u8 = sys_mmap(64) 3670 let tmv: i64 = of_manifest_count(root, "tmpl-check" as *u8, tmk, 64) 3671 var ttm_b: i64 = 0 3672 if of_memhas(out, n, "303" as *u8) == 1 { if tmv == 1 { ttm_b = 1 } } 3673 of_ck("T-TM-b a template lands as an ORDINARY v1 file (same /save contract)" as *u8, ttm_b, pass, fail) 3674 // ---- OF-A2 (sheet insight) + OF-A3 (deck slide): the AI reaches EVERY kind, in that kind's own grammar ---- 3675 // T-AI-c: the SHEET page offers the insight card (not the doc wording) -- proves the kind branch renders. 3676 n = of_handle(root, base, "GET /doc/family-budget HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3677 var tai_c: i64 = 0 3678 if of_memhas(out, n, "Add an AI insight" as *u8) == 1 { if of_memhas(out, n, "Continue with AI" as *u8) == 0 { tai_c = 1 } } 3679 of_ck("T-AI-c SHEET page offers the AI-insight card (and NOT the doc wording)" as *u8, tai_c, pass, fail) 3680 // T-AI-d: the DECK page offers the slide card. 3681 n = of_handle(root, base, "GET /doc/reunion-deck HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 55, out, 1048576) 3682 var tai_d: i64 = 0 3683 if of_memhas(out, n, "Draft the next slide" as *u8) == 1 { if of_memhas(out, n, "Add an AI insight" as *u8) == 0 { tai_d = 1 } } 3684 of_ck("T-AI-d DECK page offers the AI-slide card (and NOT the sheet wording)" as *u8, tai_d, pass, fail) 3685 // T-AI-e: POST /ai on a SHEET is now a REAL route (no longer the old doc-only 400) and degrades gracefully. 3686 let aik0: *u8 = sys_mmap(64) 3687 let aic0: i64 = of_manifest_count(root, "family-budget" as *u8, aik0, 64) 3688 bo = of_cat(bod, 0, "name=family-budget" as *u8); bod[bo] = 0 as u8 3689 ro = of_cat(req, 0, "POST /office/ai HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3690 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3691 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3692 let aik1: *u8 = sys_mmap(64) 3693 let aic1: i64 = of_manifest_count(root, "family-budget" as *u8, aik1, 64) 3694 var tai_e: i64 = 0 3695 if of_memhas(out, n, "503" as *u8) == 1 { if of_memhas(out, n, "400" as *u8) == 0 { if aic1 == aic0 { tai_e = 1 } } } 3696 of_ck("T-AI-e POST /ai on a SHEET -> 503 not 400 (kind is wired), NO version created" as *u8, tai_e, pass, fail) 3697 // ---- OF-A4 AGENT MODE (offline gate) -- the state machine + plan parser are fully provable with the seat 3698 // DOWN, so these teeth run everywhere. Only the model's WORDS need a live seat; the agency does not. 3699 // T-AG-a: the doc page offers agent mode with a goal input. 3700 n = of_handle(root, base, "GET /doc/family-letter HTTP/1.1\r\nHost: office.local\r\n\r\n" as *u8, 56, out, 1048576) 3701 var tag_a: i64 = 0 3702 if of_memhas(out, n, "Agent mode" as *u8) == 1 { if of_memhas(out, n, "/agent'><input type='hidden' name='name' value='family-letter'" as *u8) == 1 { tag_a = 1 } } 3703 of_ck("T-AG-a doc page offers agent mode with a goal input" as *u8, tag_a, pass, fail) 3704 // T-AG-b: POST /agent with a goal + seat DOWN -> graceful 503, NO version, NO agent state written. 3705 let agk0: *u8 = sys_mmap(64) 3706 let agc0: i64 = of_manifest_count(root, "family-letter" as *u8, agk0, 64) 3707 bo = of_cat(bod, 0, "name=family-letter&goal=add+a+closing" as *u8); bod[bo] = 0 as u8 3708 ro = of_cat(req, 0, "POST /office/agent HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3709 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3710 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3711 let agk1: *u8 = sys_mmap(64) 3712 let agc1: i64 = of_manifest_count(root, "family-letter" as *u8, agk1, 64) 3713 let agchk: *u8 = sys_mmap(8192) 3714 let agchkn: i64 = of_agent_read(root, "family-letter" as *u8, agchk, 8000) 3715 var tag_b: i64 = 0 3716 if of_memhas(out, n, "503" as *u8) == 1 { if agc1 == agc0 { if agchkn <= 0 { tag_b = 1 } } } 3717 of_ck("T-AG-b POST /agent seat DOWN -> 503, NO version, NO agent state (retry-safe)" as *u8, tag_b, pass, fail) 3718 // T-AG-c: no goal and no plan yet -> LOUD 400, never a silent no-op. 3719 bo = of_cat(bod, 0, "name=family-letter" as *u8); bod[bo] = 0 as u8 3720 ro = of_cat(req, 0, "POST /office/agent HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3721 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3722 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3723 of_ck("T-AG-c POST /agent with no goal -> LOUD 400" as *u8, of_memhas(out, n, "400" as *u8), pass, fail) 3724 // T-AG-d: agent mode is doc-only -> a SHEET is refused loudly (the kind guard actually bites). 3725 bo = of_cat(bod, 0, "name=family-budget&goal=summarise" as *u8); bod[bo] = 0 as u8 3726 ro = of_cat(req, 0, "POST /office/agent HTTP/1.1\r\nHost: office.local\r\nContent-Length: " as *u8) 3727 ro = of_catn(req, ro, bo); ro = of_cat(req, ro, "\r\n\r\n" as *u8); ro = of_cat(req, ro, bod) 3728 n = of_handle(root, "/office" as *u8, req, ro, out, 1048576) 3729 of_ck("T-AG-d POST /agent on a SHEET -> LOUD 400 (doc-kind guard bites)" as *u8, of_memhas(out, n, "400" as *u8), pass, fail) 3730 // T-AG-e: the plan parser turns a real multi-line model reply into ordered steps, list punctuation stripped. 3731 let agpl: *u8 = sys_mmap(4096) 3732 let agsrc: *u8 = "1. Draft the summer plans section\n2) Add a warm closing paragraph\n- Check the tone\n" as *u8 3733 let agns: i64 = of_agent_plan_parse(agsrc, of_slen(agsrc), agpl, 4000) 3734 var tag_e: i64 = 0 3735 if agns == 3 { if of_memhas(agpl, of_slen(agpl), "S Draft the summer plans section" as *u8) == 1 { if of_memhas(agpl, of_slen(agpl), "S Add a warm closing paragraph" as *u8) == 1 { tag_e = 1 } } } 3736 of_ck("T-AG-e plan parser -> 3 ordered steps, list punctuation stripped" as *u8, tag_e, pass, fail) 3737 // T-AG-f: a SINGLE-LINE reply still becomes a real plan (sentence-split fallback), not a 1-step degenerate. 3738 let agpl2: *u8 = sys_mmap(4096) 3739 let agsrc2: *u8 = "Write the intro. Then add the plans. Finally close it." as *u8 3740 let agns2: i64 = of_agent_plan_parse(agsrc2, of_slen(agsrc2), agpl2, 4000) 3741 var tag_f: i64 = 0 3742 if agns2 >= 3 { tag_f = 1 } 3743 of_ck("T-AG-f single-line reply -> sentence-split into a multi-step plan" as *u8, tag_f, pass, fail) 3744 // T-AG-g: garbage in -> NO plan (the parser refuses rather than inventing a step) = the liar-kill tooth. 3745 let agpl3: *u8 = sys_mmap(4096) 3746 let agns3: i64 = of_agent_plan_parse("..\n-\n" as *u8, 5, agpl3, 4000) 3747 var tag_g: i64 = 0 3748 if agns3 == 0 { tag_g = 1 } 3749 of_ck("T-AG-g unusable model reply -> 0 steps (refuses, never invents)" as *u8, tag_g, pass, fail) 3750 // T-AG-h: state accessors round-trip (goal, ordered steps, done cursor) through the sidecar format. 3751 let agst: *u8 = "G ship it\nS one\nS two\nD 1\n" as *u8 3752 let agstn: i64 = of_slen(agst) 3753 let agtmp: *u8 = sys_mmap(256) 3754 var tag_h: i64 = 0 3755 if of_agent_tagcount(agst, agstn, 83) == 2 { 3756 if of_agent_done(agst, agstn) == 1 { 3757 of_agent_tagline(agst, agstn, 83, 1, agtmp, 256) 3758 if of_seq(agtmp, "two" as *u8) == 1 { tag_h = 1 } 3759 } 3760 } 3761 of_ck("T-AG-h agent state round-trips (2 steps, cursor=1, step[1]='two')" as *u8, tag_h, pass, fail) 3762 // under the gate (g_of_gv armed) the caller's gv_verdict is the ONE tally and the LAST line -- two verdict 3763 // lines would be two rulers, and the referee anchors on the last one. 3764 if g_of_gv != 0 { if fail[0] == 0 { return 0 } return 1 } 3765 p("NX-OFFICE SELFTEST pass=" as *u8); pn(pass[0]); p(" fail=" as *u8); pn(fail[0]) 3766 if fail[0] == 0 { p(" verdict=GREEN (the office round-trips: create/edit/version/preview/download, additive by construction)\n" as *u8); return 0 } 3767 p(" verdict=RED\n" as *u8) 3768 return 1 3769}