code wiki / _hdl_build / nx_reader_library_gate.nx

nx_reader_library_gate.nx source

↩ module page · 109 lines · 7474 B

1import "nx_gate_grow.nx" 2import "nx_gate_gn.nx" 3import "nx_gate_read.nx" 4// nx_reader_library_gate.nx -- SOVEREIGN referee for the shared/personal LIBRARY spine (FLAT-SLUG convention: 5// a personal book's slug IS "u_<ukey>_<name>", so the owner is encoded in the slug the serve routes key off). 6// The core property: PRIVACY BY CONSTRUCTION -- user B can never name/reach user A's personal book. chdir /tmp. 7// T0 rl_slug_guard: shared slug ok for all; A's personal slug ok for A / denied for B; ukey-prefix (not whole) 8// denied. rl_may_access path form: reader/<shared> ok; reader/u_<A>_x ok for A / denied for B; "../" denied. 9// T1 rl_add_personal -> index row "u_<kA>_mymanga\t<title>", dir reader/u_<kA>_mymanga created; idempotent (0) 10// T2 list_personal(A) shows it; list_personal(B) EMPTY 11// T3 guard the REAL fixture paths (A yes / B no) 12// T4 promote: reader/u_<kA>_mymanga -> reader/mymanga + shared index gets "mymanga"; source gone 13// T5 NEG promote: missing -> 0 ; B promoting A's slug -> -1 (not owned) ; shared-exists -> -1 (never clobber) 14// GREEN iff 6/6. license_tier: ORIGINAL expect_exit: 0 15import "nx_syscalls.nx" 16import "nx_reader_library.nx" 17 18func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 19func g_has(hay: *u8, n: i64, needle: *u8) -> i64 { 20 var nn: i64 = 0; while needle[nn] != (0 as u8) { nn = nn + 1 } 21 if nn == 0 { return 0 } 22 var i: i64 = 0 23 while i + nn <= n { var m: i64 = 1; var j: i64 = 0; while j < nn { if (hay[i + j] as i64) != (needle[j] as i64) { m = 0; j = nn } else { j = j + 1 } } if m == 1 { return 1 } i = i + 1 } 24 return 0 25} 26func g_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 27func g_mkdir(path: *u8) -> i64 { __syscall(258, 0 - 100, path as i64, 0x1ed, 0, 0, 0); return 0 } 28func g_wr(path: *u8, s: *u8, n: i64) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd >= 0 { sys_write(fd, s, n); sys_close(fd) } return 0 } 29func g_unlink(path: *u8) -> i64 { __syscall(263, 0 - 100, path, 0, 0, 0, 0); return 0 } 30 31func main() -> i64 { 32 gw("reader-library SOVEREIGN gate (flat-slug shared/personal isolation-by-construction)\n" as *u8) 33 if sys_chdir("/tmp" as *u8) != 0 { gw("CHDIR /tmp FAIL\n" as *u8); sys_exit(1) } 34 g_mkdir("knowledge" as *u8); g_mkdir("knowledge/staging" as *u8); g_mkdir("knowledge/staging/media" as *u8); g_mkdir("knowledge/staging/media/reader" as *u8) 35 36 let kA: *u8 = "elder_aa11bb22" as *u8 37 let kB: *u8 = "brad_cc33dd44" as *u8 38 var pass: i64 = 0 39 40 // ---- T0 the guard + path predicate ---- 41 var t0: i64 = 1 42 if rl_slug_guard(kA, "sharedbook" as *u8) != 1 { t0 = 0 } // shared ok for A 43 if rl_slug_guard(kB, "sharedbook" as *u8) != 1 { t0 = 0 } // shared ok for B 44 if rl_slug_guard(kA, "u_elder_aa11bb22_mymanga" as *u8) != 1 { t0 = 0 } // A's personal ok for A 45 if rl_slug_guard(kB, "u_elder_aa11bb22_mymanga" as *u8) != 0 { t0 = 0 } // A's personal DENIED for B 46 if rl_slug_guard(kA, "u_elder_aa11bb2_x" as *u8) != 0 { t0 = 0 } // ukey PREFIX (not whole) DENIED 47 if rl_may_access(kA, "reader/sharedbook/cbx.json" as *u8) != 1 { t0 = 0 } 48 if rl_may_access(kA, "reader/u_elder_aa11bb22_mymanga/page000.jpg" as *u8) != 1 { t0 = 0 } 49 if rl_may_access(kB, "reader/u_elder_aa11bb22_mymanga/page000.jpg" as *u8) != 0 { t0 = 0 } 50 if rl_may_access(kA, "reader/u_elder_aa11bb22_mymanga/../brad/x" as *u8) != 0 { t0 = 0 } // traversal 51 pass = pass + grow("T0 rl_slug_guard + rl_may_access: A ok / B denied / prefix / shared / traversal\x00" as *u8, t0) 52 53 // ---- T1 add personal + idempotent ---- 54 g_unlink("knowledge/staging/media/idx_book_personal_elder_aa11bb22.wsl" as *u8) 55 let add1: i64 = rl_add_personal(kA, "mymanga" as *u8, "My Secret Manga" as *u8, 15) 56 let add2: i64 = rl_add_personal(kA, "mymanga" as *u8, "My Secret Manga" as *u8, 15) 57 var t1: i64 = 0 58 let ib: *u8 = sys_mmap(4096) 59 let inn: i64 = g_read("knowledge/staging/media/idx_book_personal_elder_aa11bb22.wsl" as *u8, ib, 4096) 60 if add1 == 1 { if add2 == 0 { if inn > 0 { if g_has(ib, inn, "u_elder_aa11bb22_mymanga\tMy Secret Manga" as *u8) == 1 { if g_exists("knowledge/staging/media/reader/u_elder_aa11bb22_mymanga" as *u8) == 1 { t1 = 1 } } } } } 61 pass = pass + grow("T1 rl_add_personal -> index row (full slug) + dir + idempotent\x00" as *u8, t1) 62 63 // ---- T2 list isolation ---- 64 let lb: *u8 = sys_mmap(8192) 65 let ln: i64 = rl_list_personal_json(kA, lb, 8192) 66 var t2: i64 = 0 67 if g_has(lb, ln, "\"slug\":\"u_elder_aa11bb22_mymanga\"" as *u8) == 1 { if g_has(lb, ln, "My Secret Manga" as *u8) == 1 { 68 let lb2: *u8 = sys_mmap(8192); let ln2: i64 = rl_list_personal_json(kB, lb2, 8192) 69 if g_has(lb2, ln2, "mymanga" as *u8) == 0 { if g_has(lb2, ln2, "\"items\":[]" as *u8) == 1 { t2 = 1 } } 70 } } 71 pass = pass + grow("T2 list_personal(A) shows it; list_personal(B) EMPTY\x00" as *u8, t2) 72 73 // ---- T3 real fixture path guard ---- 74 g_mkdir("knowledge/staging/media/reader/u_elder_aa11bb22_mymanga" as *u8) 75 g_wr("knowledge/staging/media/reader/u_elder_aa11bb22_mymanga/cbx.json" as *u8, "{\"pages\":[{\"idx\":0,\"file\":\"page000.jpg\"}]}" as *u8, 43) 76 var t3: i64 = 0 77 if rl_may_access(kA, "reader/u_elder_aa11bb22_mymanga/cbx.json" as *u8) == 1 { if rl_may_access(kB, "reader/u_elder_aa11bb22_mymanga/cbx.json" as *u8) == 0 { t3 = 1 } } 78 pass = pass + grow("T3 guard REAL fixture paths (A yes / B no)\x00" as *u8, t3) 79 80 // ---- T4 promote ---- 81 g_unlink("knowledge/staging/media/idx_book_shared.wsl" as *u8) 82 g_unlink("knowledge/staging/media/reader/mymanga/cbx.json" as *u8) 83 let pr: i64 = rl_promote_to_shared(kA, "u_elder_aa11bb22_mymanga" as *u8) 84 var t4: i64 = 0 85 if pr == 1 { 86 if g_exists("knowledge/staging/media/reader/mymanga/cbx.json" as *u8) == 1 { 87 if g_exists("knowledge/staging/media/reader/u_elder_aa11bb22_mymanga/cbx.json" as *u8) == 0 { 88 let sib: *u8 = sys_mmap(1024); let sin: i64 = g_read("knowledge/staging/media/idx_book_shared.wsl" as *u8, sib, 1024) 89 if sin > 0 { if g_has(sib, sin, "mymanga" as *u8) == 1 { t4 = 1 } } 90 } 91 } 92 } 93 pass = pass + grow("T4 promote: u_<kA>_mymanga -> reader/mymanga + shared idx + source gone\x00" as *u8, t4) 94 95 // ---- T5 NEG promote ---- 96 var t5: i64 = 0 97 let prn: i64 = rl_promote_to_shared(kA, "u_elder_aa11bb22_nosuch" as *u8) // missing -> 0 98 // recreate personal + owner-mismatch + shared-exists 99 g_mkdir("knowledge/staging/media/reader/u_elder_aa11bb22_mymanga" as *u8) 100 g_wr("knowledge/staging/media/reader/u_elder_aa11bb22_mymanga/cbx.json" as *u8, "{}" as *u8, 2) 101 let prB: i64 = rl_promote_to_shared(kB, "u_elder_aa11bb22_mymanga" as *u8) // B not owner -> -1 102 let prc: i64 = rl_promote_to_shared(kA, "u_elder_aa11bb22_mymanga" as *u8) // shared exists -> -1 103 if prn == 0 { if prB == 0 - 1 { if prc == 0 - 1 { t5 = 1 } } } 104 pass = pass + grow("T5 NEG promote: missing->0 ; not-owner->-1 ; shared-exists->-1\x00" as *u8, t5) 105 106 gw("pass=" as *u8); gn(pass); gw("/6\n" as *u8) 107 if pass == 6 { gw("verdict=GREEN (flat-slug shared/personal: owner-in-slug isolation + per-user index + owner-only promote, fail-closed)\n" as *u8); sys_exit(0); return 0 } 108 gw("verdict=RED\n" as *u8); sys_exit(1); return 1 109}