code wiki / wiki / nx_wiki_license.nx

nx_wiki_license.nx source

↩ module page · 153 lines · 7527 B

1// nx_wiki_license.nx -- PER-SOURCE LICENSE LAYER for the no-link-rot archive. 2// 3// THE EXCEED OVER WIKIPEDIA (anti-pushout, done RIGHT): 4// We render a cited supporting source INLINE in the wiki -- but ONLY when the 5// license permits us to host/redistribute it. This module is the gate that 6// decides hostable vs link-only. Getting this WRONG is the one unacceptable 7// failure: inlining content we are not licensed to host. So the rule is sealed 8// here, data-driven (per-source tag in the archive store), and the cite-render 9// asks THIS module -- never guesses. 10// 11// LICENSE CLASSES (sealed enum; values are stable on-disk so a stored tag keeps 12// meaning forever -- additive-only, never renumber): 13// 0 UNKNOWN not hostable (we don't know -> we don't inline) 14// 1 PUBLIC_DOMAIN hostable, no attribution required 15// 2 CC0 hostable, no attribution required (PD-equivalent dedication) 16// 3 CC_BY hostable, attribution required 17// 4 CC_BY_SA hostable, attribution required (share-alike) 18// 5 CC_BY_NC hostable, attribution required (non-commercial) 19// 6 CC_BY_ND hostable, attribution required (no-derivatives -- verbatim 20// redistribution, which inline display IS, is permitted) 21// 7 CC_BY_NC_SA hostable, attribution required 22// 8 PROPRIETARY NOT hostable (all-rights-reserved -> link only) 23// 24// HOSTABLE = "the license permits us to redistribute / display the verbatim 25// source bytes to a reader". Public-domain + CC0 + every Creative-Commons 26// variant grant redistribution (the NC/ND/SA conditions constrain commercial 27// use / derivatives / relicensing, NOT verbatim display, which is exactly what 28// an inline read is). PROPRIETARY and UNKNOWN are the deny set. 29// 30// STORE: the per-source tag lives in the SAME content-addressed seg_store the 31// archive uses (prefix WAR_PREFIX from nx_wiki_archive.nx), under key 32// wikilic:<cid> -> one byte = the license class (0..8) 33// keyed by the SOURCE's CID so the license travels with the content address. 34// Absent tag => UNKNOWN (fail-closed: an un-tagged source is never inlined). 35// 36// IMPORTS: nx_wiki_archive.nx (for WAR_PREFIX + the seg_store API it re-exports 37// transitively). NishiLang's resolver de-dups imports by module identity (the 38// archive itself imports nx_seg_store + nx_canon_cid; importing the archive here 39// splices each ONCE), so no double-import nxasm-rc6 landmine. Pure NishiLang, 40// NO SQL, NO .sh/.py/.js, no new .tsv/.conf. license_tier: ORIGINAL 41import "nx_wiki_archive.nx" 42 43// ===== sealed license-class enum (stable on-disk values) ===================== 44const NXLIC_UNKNOWN: i64 = 0 45const NXLIC_PUBLIC_DOMAIN: i64 = 1 46const NXLIC_CC0: i64 = 2 47const NXLIC_CC_BY: i64 = 3 48const NXLIC_CC_BY_SA: i64 = 4 49const NXLIC_CC_BY_NC: i64 = 5 50const NXLIC_CC_BY_ND: i64 = 6 51const NXLIC_CC_BY_NC_SA: i64 = 7 52const NXLIC_PROPRIETARY: i64 = 8 53 54// manifest segment-scan cap for license-tag reads (matches archive callers; 55// the archive is a handful of committed segments, this is generous headroom). 56const NXLIC_CAP: i64 = 64 57 58// ---- human-readable class name (for the inline card's attribution footer) ---- 59// Returns a NUL-terminated literal. Unknown/out-of-range -> "Unknown license". 60func nx_wiki_license_name(cls: i64) -> *u8 { 61 if cls == NXLIC_PUBLIC_DOMAIN { return "Public Domain" as *u8 } 62 if cls == NXLIC_CC0 { return "CC0 1.0" as *u8 } 63 if cls == NXLIC_CC_BY { return "CC BY 4.0" as *u8 } 64 if cls == NXLIC_CC_BY_SA { return "CC BY-SA 4.0" as *u8 } 65 if cls == NXLIC_CC_BY_NC { return "CC BY-NC 4.0" as *u8 } 66 if cls == NXLIC_CC_BY_ND { return "CC BY-ND 4.0" as *u8 } 67 if cls == NXLIC_CC_BY_NC_SA { return "CC BY-NC-SA 4.0" as *u8 } 68 if cls == NXLIC_PROPRIETARY { return "Proprietary - all rights reserved" as *u8 } 69 return "Unknown license" as *u8 70} 71 72// ---- THE LIAR-KILL DECISION: may we host/inline this source's bytes? ---- 73// 1 = yes (PD, CC0, every CC variant -- redistribution/display granted) 74// 0 = no (PROPRIETARY, UNKNOWN -- fail-closed deny set) 75// This is the ONLY place the hostable rule lives; cite-render calls it and 76// trusts it (Cardinal 12: trust internal, validate boundaries). 77func nx_wiki_license_hostable(cls: i64) -> i64 { 78 if cls == NXLIC_PUBLIC_DOMAIN { return 1 } 79 if cls == NXLIC_CC0 { return 1 } 80 if cls == NXLIC_CC_BY { return 1 } 81 if cls == NXLIC_CC_BY_SA { return 1 } 82 if cls == NXLIC_CC_BY_NC { return 1 } 83 if cls == NXLIC_CC_BY_ND { return 1 } 84 if cls == NXLIC_CC_BY_NC_SA { return 1 } 85 // NXLIC_UNKNOWN, NXLIC_PROPRIETARY, and anything else -> deny 86 return 0 87} 88 89// ---- does this license require attribution when we display it? ---- 90// PD + CC0 dedicate to the public domain / waive attribution; every BY-* CC 91// license requires it. Non-hostable classes return 0 (moot -- never displayed). 92func nx_wiki_license_attribution_required(cls: i64) -> i64 { 93 if cls == NXLIC_CC_BY { return 1 } 94 if cls == NXLIC_CC_BY_SA { return 1 } 95 if cls == NXLIC_CC_BY_NC { return 1 } 96 if cls == NXLIC_CC_BY_ND { return 1 } 97 if cls == NXLIC_CC_BY_NC_SA { return 1 } 98 return 0 99} 100 101// ---- build the "wikilic:<cid>" tag key into out (NUL-terminated) ---- 102// cid is NUL-terminated; reuses war_cat (the archive's concat helper). 103func nx_wiki_lickey(cid: *u8, out: *u8) -> i64 { 104 var o: i64 = 0 105 o = war_cat(out, o, "wikilic:" as *u8) 106 o = war_cat(out, o, cid) 107 out[o] = 0 as u8 108 return o 109} 110 111// ---- SETTER: tag a source CID with a license class ---- 112// Appends wikilic:<cid> -> 1 byte (cls) into an OPEN writer; the caller commits 113// (same temp->rename discipline as war_archive_page; idempotent by last-writer). 114// Validates cls into the sealed range at the boundary (UNKNOWN if out of range, 115// so a garbage class can never become "hostable"). Returns ss_add rc (0 ok). 116func nx_wiki_license_set_w(w: *i64, cid: *u8, cls: i64) -> i64 { 117 var c: i64 = cls 118 if c < 0 { c = NXLIC_UNKNOWN } 119 if c > NXLIC_PROPRIETARY { c = NXLIC_UNKNOWN } 120 let lk: *u8 = sys_mmap(128) 121 nx_wiki_lickey(cid, lk) 122 let vb: *u8 = sys_mmap(8) 123 vb[0] = c as u8 124 return ss_add(w, 1, lk, vb, 1) 125} 126 127// ---- SETTER (self-contained): begin+set+commit in one call ---- 128// Convenience for callers that just want to stamp one source's license. 129// segid lets the caller pick a fresh segment id (additive). Returns commit rc. 130func nx_wiki_license_set(prefix: *u8, cid: *u8, cls: i64, segid: i64) -> i64 { 131 let w: *i64 = ss_begin() 132 let r: i64 = nx_wiki_license_set_w(w, cid, cls) 133 if r != 0 { return r } 134 return ss_commit(prefix, w, segid) 135} 136 137// ---- GETTER: read a source CID's license class from the committed store ---- 138// Returns the stored class (0..8), or NXLIC_UNKNOWN if no tag exists 139// (fail-closed). prefix = the archive store prefix (production: WAR_PREFIX). 140func nx_wiki_license_get(prefix: *u8, cid: *u8) -> i64 { 141 let lk: *u8 = sys_mmap(128) 142 nx_wiki_lickey(cid, lk) 143 let pp: *i64 = sys_mmap(16) as *i64 144 let ll: *i64 = sys_mmap(16) as *i64 145 let r: i64 = ss_get_cap(prefix, lk, pp, ll, NXLIC_CAP) 146 if r != 1 { return NXLIC_UNKNOWN } 147 if ll[0] < 1 { return NXLIC_UNKNOWN } 148 let src: *u8 = pp[0] as *u8 149 let v: i64 = src[0] 150 if v < 0 { return NXLIC_UNKNOWN } 151 if v > NXLIC_PROPRIETARY { return NXLIC_UNKNOWN } 152 return v 153}