code wiki / _hdl_build / nx_trustfence_lib.nx

nx_trustfence_lib.nx source

↩ module page · 140 lines · 6682 B

1// nx_trustfence_lib.nx -- LangIntel LI9 SHARED trust-tier classifier (pure, NO I/O, NO main). 2// SEALED verdict codes so BOTH the CLI (nx_langintel_trustfence) and the CI fixture gate 3// (nx_langintel_trustfence_gate) reuse ONE ltg_classify_code = single source of truth (Rule 15 DRY, 4// the atlas OO-consolidation directive). Provenance-only trust: tier-1 IFF merged + real merge_commit_sha + 5// base.repo.full_name == the canonical owner/repo (an attacker cannot merge into it). Branch identity is 6// evidence, NOT gated (default_branch is CURRENT, base.ref is HISTORICAL -- master->main rename would 7// false-reject a genuine gold patch). Consolidates onto nx_ingest_base (ib_find/ib_jstr/ib_slen). 8// Read-only external, NO exec (Rule 26). license_tier: ORIGINAL 9import "nx_ingest_base.nx" 10import "nx_syscalls.nx" 11 12const LTG_VCAP: i64 = 1024 13 14// sealed verdicts (Rule 6 structured): 15const LTG_ACCEPT: i64 = 1 16const LTG_REJ_NOT_MERGED: i64 = 2 17const LTG_REJ_NO_MERGE_SHA: i64 = 3 18const LTG_REJ_NO_BASE: i64 = 4 19const LTG_REJ_BASE_SPAN: i64 = 5 20const LTG_REJ_NO_BASE_REF: i64 = 6 21const LTG_REJ_NO_BASE_REPO: i64 = 7 22const LTG_REJ_BASE_REPO_SPAN: i64 = 8 23const LTG_REJ_NO_FULL_NAME: i64 = 9 24const LTG_REJ_NOT_CANONICAL: i64 = 10 25 26func ltg_qkey(word: *u8, out: *u8) -> i64 { 27 out[0] = 34 as u8 28 var i: i64 = 0 29 while word[i] != (0 as u8) { out[i+1] = word[i]; i = i + 1 } 30 out[i+1] = 34 as u8 31 out[i+2] = 0 as u8 32 return 0 33} 34func ltg_streq(a: *u8, b: *u8) -> i64 { 35 var i: i64 = 0 36 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 37 if b[i] != (0 as u8) { return 0 } 38 return 1 39} 40// balanced {..} object at/after `from`, string-aware (ignores braces in quoted strings, honors backslash). 41// se[0]='{' index, se[1]=index AFTER matching '}'. 1 ok / 0 unbalanced. 42func ltg_obj_span(buf: *u8, n: i64, from: i64, se: *i64) -> i64 { 43 var i: i64 = from 44 var start: i64 = 0 - 1 45 var g: i64 = 1 46 while g == 1 { 47 if i >= n { g = 0 } else { if buf[i] == (123 as u8) { start = i; g = 0 } else { i = i + 1 } } 48 } 49 if start < 0 { return 0 } 50 var depth: i64 = 0 51 var instr: i64 = 0 52 var j: i64 = start 53 var go: i64 = 1 54 while go == 1 { 55 if j >= n { go = 0 } 56 else { 57 let c: i64 = buf[j] as i64 58 if instr == 1 { 59 if c == 92 { j = j + 1 } else { if c == 34 { instr = 0 } } 60 } else { 61 if c == 34 { instr = 1 } else { if c == 123 { depth = depth + 1 } else { if c == 125 { depth = depth - 1; if depth == 0 { se[0] = start; se[1] = j + 1; return 1 } } } } 62 } 63 j = j + 1 64 } 65 } 66 return 0 67} 68// 1 if key's bool value is true, 0 if false/other, -1 if key absent. scans [from,n). 69func ltg_bool(buf: *u8, n: i64, key: *u8, from: i64) -> i64 { 70 let p: i64 = ib_find(buf, n, key, from) 71 if p < 0 { return 0 - 1 } 72 var i: i64 = p + ib_slen(key) 73 var g: i64 = 1 74 while g == 1 { 75 if i >= n { return 0 - 1 } 76 let c: i64 = buf[i] as i64 77 if c == 58 { i = i + 1 } else { if c == 32 { i = i + 1 } else { if c == 9 { i = i + 1 } else { if c == 10 { i = i + 1 } else { if c == 13 { i = i + 1 } else { g = 0 } } } } } 78 } 79 if buf[i] == (116 as u8) { return 1 } 80 return 0 81} 82// PURE classifier: fills msha/bfull/bref/bdef (caller buffers, LTG_VCAP; empty if not reached) with the 83// extracted evidence, returns a sealed LTG_* code. NO I/O -- the CLI and the CI gate both call this. 84func ltg_classify_code(buf: *u8, n: i64, expect_full: *u8, msha: *u8, bfull: *u8, bref: *u8, bdef: *u8) -> i64 { 85 msha[0] = 0 as u8; bfull[0] = 0 as u8; bref[0] = 0 as u8; bdef[0] = 0 as u8 86 let bs0: i64 = ib_find(buf, n, "{" as *u8, 0) 87 var bs: i64 = 0 88 if bs0 >= 0 { bs = bs0 } 89 let kb: *u8 = sys_mmap(128) 90 ltg_qkey("merged" as *u8, kb) 91 let merged: i64 = ltg_bool(buf, n, kb, bs) 92 if merged != 1 { return LTG_REJ_NOT_MERGED } 93 ltg_qkey("merge_commit_sha" as *u8, kb) 94 let mr: i64 = ib_jstr(buf, n, kb, bs, msha, LTG_VCAP) 95 if mr < 0 { return LTG_REJ_NO_MERGE_SHA } 96 let bse: *i64 = sys_mmap(16) as *i64 97 ltg_qkey("base" as *u8, kb) 98 let bp: i64 = ib_find(buf, n, kb, bs) 99 if bp < 0 { return LTG_REJ_NO_BASE } 100 if ltg_obj_span(buf, n, bp, bse) == 0 { return LTG_REJ_BASE_SPAN } 101 let bstart: i64 = bse[0] 102 let bend: i64 = bse[1] 103 ltg_qkey("ref" as *u8, kb) 104 let rr: i64 = ib_jstr(buf, bend, kb, bstart, bref, LTG_VCAP) 105 if rr < 0 { return LTG_REJ_NO_BASE_REF } 106 let rse: *i64 = sys_mmap(16) as *i64 107 ltg_qkey("repo" as *u8, kb) 108 let rp: i64 = ib_find(buf, bend, kb, bstart) 109 if rp < 0 { return LTG_REJ_NO_BASE_REPO } 110 if ltg_obj_span(buf, bend, rp, rse) == 0 { return LTG_REJ_BASE_REPO_SPAN } 111 let rstart: i64 = rse[0] 112 let rend: i64 = rse[1] 113 ltg_qkey("full_name" as *u8, kb) 114 let fr: i64 = ib_jstr(buf, rend, kb, rstart, bfull, LTG_VCAP) 115 if fr < 0 { return LTG_REJ_NO_FULL_NAME } 116 ltg_qkey("default_branch" as *u8, kb) 117 let dr: i64 = ib_jstr(buf, rend, kb, rstart, bdef, LTG_VCAP) 118 if dr < 0 { bdef[0] = 63 as u8; bdef[1] = 0 as u8 } 119 if ltg_streq(bfull, expect_full) == 0 { return LTG_REJ_NOT_CANONICAL } 120 return LTG_ACCEPT 121} 122func ltg_is_accept(code: i64) -> i64 { if code == LTG_ACCEPT { return 1 } return 0 } 123func ltg_reason(code: i64) -> *u8 { 124 if code == LTG_REJ_NOT_MERGED { return "pr-not-merged" as *u8 } 125 if code == LTG_REJ_NO_MERGE_SHA { return "no-merge-commit-sha" as *u8 } 126 if code == LTG_REJ_NO_BASE { return "no-base-object" as *u8 } 127 if code == LTG_REJ_BASE_SPAN { return "base-span-unbalanced" as *u8 } 128 if code == LTG_REJ_NO_BASE_REF { return "no-base-ref" as *u8 } 129 if code == LTG_REJ_NO_BASE_REPO { return "no-base-repo" as *u8 } 130 if code == LTG_REJ_BASE_REPO_SPAN { return "base-repo-span-unbalanced" as *u8 } 131 if code == LTG_REJ_NO_FULL_NAME { return "no-base-repo-full_name" as *u8 } 132 if code == LTG_REJ_NOT_CANONICAL { return "base-repo-not-canonical" as *u8 } 133 return "unknown" as *u8 134} 135func ltg_fix(code: i64) -> *u8 { 136 if code == LTG_REJ_NOT_MERGED { return "ingest ONLY merged PRs -- an unmerged/closed PR is not a canonical fix; skip it" as *u8 } 137 if code == LTG_REJ_NO_MERGE_SHA { return "require a real merge_commit_sha -- null means not actually merged into a branch" as *u8 } 138 if code == LTG_REJ_NOT_CANONICAL { return "base.repo.full_name != expected canonical owner/repo -- likely a FORK or wrong project; ingest ONLY from the canonical repo (an attacker cannot merge into it)" as *u8 } 139 return "malformed PR json -- refetch via nx_ghfetch <pr-api-url> <file>" as *u8 140}