code wiki / (root) / nx_seed_bank.nx

nx_seed_bank.nx source

↩ module page · 256 lines · 9349 B

1// nx_seed_bank.nx -- multi-genotype cold-storage backup substrate. 2// 3// Biology: a seed bank (Svalbard Global Seed Vault, Millennium Seed Bank, 4// indigenous community seed banks) preserves GENETIC DIVERSITY in dormant 5// form across decades-to-centuries. Each accession is content-addressed, 6// labeled with provenance, and can be retrieved + germinated when needed 7// to restore a lost cultivar / population. Diversity is the load-bearing 8// property: a monoculture seed bank is a single point of failure. 9// 10// In Nishi: persistent cold storage of substrate genotype snapshots 11// (config + schema + seed primitives) so a damaged installation can be 12// restored to known-green from a chosen accession. Composes with 13// [[nx_seed]] (the seed primitive is what gets stored), [[nx_prune]] + 14// [[nx_regenerate]] (prune-rebuild reads from seed bank), [[feedback- 15// thymus-sovereignty-audit-soma-germline]] (only germline accessions 16// preserved; soma is regenerable from germline), [[feedback-end-to-end- 17// bit-traceability-architecture]] (every accession is content-addressed + 18// provenance-stamped). 19// 20// V1 ships sealed accession-kind enum + provenance-stamped record + 21// retrieval + diversity audit (HHI-style monoculture detector). 22 23import "nx_syscalls.nx" 24import "nx_tier.nx" 25const NX_MAGIC_1024: i64 = 1024 26 27// ===== Sealed enum: NxAccessionKind =============================== 28 29const NX_SB_KIND_FULL_GENOTYPE: nx_int = 0 // complete germline snapshot 30const NX_SB_KIND_CONFIG_ONLY: nx_int = 1 // operator preferences 31const NX_SB_KIND_SCHEMA_ONLY: nx_int = 2 // data layout 32const NX_SB_KIND_KEY_MATERIAL: nx_int = 3 // sovereign keys (encrypted) 33const NX_SB_KIND_FAMILY_CORPUS: nx_int = 4 // family-generated content 34const NX_SB_KIND_TEK_ARCHIVE: nx_int = 5 // traditional knowledge 35const NX_SB_KIND_HEIRLOOM_CULTIVAR: nx_int = 6 // cultural/family heritage data 36const NX_SB_KIND_N: nx_int = 7 37 38// ===== Sealed enum: NxAccessionStatus ============================= 39 40const NX_SB_STATUS_DORMANT: nx_int = 0 41const NX_SB_STATUS_VERIFIED: nx_int = 1 // hash + signature checked 42const NX_SB_STATUS_RETRIEVED: nx_int = 2 43const NX_SB_STATUS_CORRUPTED: nx_int = 3 // hash mismatch on verify 44const NX_SB_STATUS_N: nx_int = 4 45 46// ===== Sealed enum: NxSeedBankVerdict ============================= 47 48const NX_SB_V_OK: nx_int = 0 49const NX_SB_V_OK_HEALTHY_DIVERSITY: nx_int = 1 50const NX_SB_V_MONOCULTURE_WARNING: nx_int = 2 // HHI too concentrated 51const NX_SB_V_CORRUPTION_DETECTED: nx_int = 3 52const NX_SB_V_INVALID: nx_int = 4 53const NX_SB_V_NULL: nx_int = 5 54const NX_SB_V_N: nx_int = 6 55 56// ===== Struct: NxAccession ======================================== 57 58struct NxAccession { 59 accession_id: nx_int, 60 kind: nx_int, 61 content_hash: nx_size, 62 provenance_hash: nx_size, // signer chain 63 stored_at_us: nx_size, 64 last_verified_us: nx_size, 65 bytes_stored: nx_size, 66 status: nx_int, 67} 68 69const NX_SB_A_BYTES: nx_int = 64 70 71struct NxSeedBank { 72 accessions: *u8, 73 n_accessions: nx_int, 74 capacity: nx_int, 75 next_accession_id: nx_int, 76 monoculture_threshold_q10: nx_int, // HHI Q10 threshold for warning 77 formed_at_us: nx_size, 78} 79 80const NX_SB_BYTES: nx_int = 48 81 82// ===== Validators ================================================= 83 84func nx_sb_kind_is_valid(k: nx_int) -> nx_int { 85 if k < 0 { return 0 } 86 if k >= NX_SB_KIND_N { return 0 } 87 return 1 88} 89 90func nx_sb_status_is_valid(s: nx_int) -> nx_int { 91 if s < 0 { return 0 } 92 if s >= NX_SB_STATUS_N { return 0 } 93 return 1 94} 95 96func nx_sb_v_is_valid(v: nx_int) -> nx_int { 97 if v < 0 { return 0 } 98 if v >= NX_SB_V_N { return 0 } 99 return 1 100} 101 102// ===== Constructor ================================================ 103 104func nx_sb_new(capacity: nx_int, 105 monoculture_threshold_q10: nx_int, 106 now_us: nx_size) -> *NxSeedBank { 107 if capacity <= 0 { return 0 as *NxSeedBank } 108 if monoculture_threshold_q10 <= 0 { return 0 as *NxSeedBank } 109 if monoculture_threshold_q10 > NX_MAGIC_1024 { return 0 as *NxSeedBank } 110 let raw: *u8 = sys_mmap(NX_SB_BYTES) 111 let b: *NxSeedBank = raw as *NxSeedBank 112 b.accessions = sys_mmap(capacity * NX_SB_A_BYTES) 113 b.n_accessions = 0 114 b.capacity = capacity 115 b.next_accession_id = 1 116 b.monoculture_threshold_q10 = monoculture_threshold_q10 117 b.formed_at_us = now_us 118 return b 119} 120 121func _sb_acc_at(b: *NxSeedBank, idx: nx_int) -> *NxAccession { 122 if idx < 0 { return 0 as *NxAccession } 123 if idx >= b.n_accessions { return 0 as *NxAccession } 124 let off: nx_int = idx * NX_SB_A_BYTES 125 return (b.accessions + off) as *NxAccession 126} 127 128// ===== Store accession ============================================ 129 130func nx_sb_store(b: *NxSeedBank, 131 kind: nx_int, 132 content_hash: nx_size, 133 provenance_hash: nx_size, 134 bytes_stored: nx_size, 135 now_us: nx_size) -> nx_int { 136 if (b as i64) == 0 { return 0 } 137 if nx_sb_kind_is_valid(kind) == 0 { return 0 } 138 if b.n_accessions >= b.capacity { return 0 } 139 if content_hash == 0 { return 0 } 140 let off: nx_int = b.n_accessions * NX_SB_A_BYTES 141 let a: *NxAccession = (b.accessions + off) as *NxAccession 142 a.accession_id = b.next_accession_id 143 a.kind = kind 144 a.content_hash = content_hash 145 a.provenance_hash = provenance_hash 146 a.stored_at_us = now_us 147 a.last_verified_us = now_us 148 a.bytes_stored = bytes_stored 149 a.status = NX_SB_STATUS_VERIFIED 150 b.n_accessions = b.n_accessions + 1 151 b.next_accession_id = b.next_accession_id + 1 152 return a.accession_id 153} 154 155func nx_sb_find(b: *NxSeedBank, accession_id: nx_int) -> *NxAccession { 156 if (b as i64) == 0 { return 0 as *NxAccession } 157 var i: nx_int = 0 158 while i < b.n_accessions { 159 let a: *NxAccession = _sb_acc_at(b, i) 160 if a.accession_id == accession_id { return a } 161 i = i + 1 162 } 163 return 0 as *NxAccession 164} 165 166// ===== Verify integrity =========================================== 167 168func nx_sb_verify(b: *NxSeedBank, 169 accession_id: nx_int, 170 observed_hash: nx_size, 171 now_us: nx_size) -> nx_int { 172 if (b as i64) == 0 { return NX_SB_V_NULL } 173 let a: *NxAccession = nx_sb_find(b, accession_id) 174 if (a as i64) == 0 { return NX_SB_V_INVALID } 175 if a.content_hash != observed_hash { 176 a.status = NX_SB_STATUS_CORRUPTED 177 return NX_SB_V_CORRUPTION_DETECTED 178 } 179 a.status = NX_SB_STATUS_VERIFIED 180 a.last_verified_us = now_us 181 return NX_SB_V_OK 182} 183 184// ===== Retrieve =================================================== 185 186func nx_sb_retrieve(b: *NxSeedBank, 187 accession_id: nx_int, 188 now_us: nx_size) -> nx_size { 189 if (b as i64) == 0 { return 0 } 190 let a: *NxAccession = nx_sb_find(b, accession_id) 191 if (a as i64) == 0 { return 0 } 192 if a.status == NX_SB_STATUS_CORRUPTED { return 0 } 193 a.status = NX_SB_STATUS_RETRIEVED 194 return a.content_hash 195} 196 197// ===== Aggregations + diversity audit ============================= 198 199func nx_sb_count_by_kind(b: *NxSeedBank, kind: nx_int) -> nx_int { 200 if (b as i64) == 0 { return 0 } 201 var count: nx_int = 0 202 var i: nx_int = 0 203 while i < b.n_accessions { 204 let a: *NxAccession = _sb_acc_at(b, i) 205 if a.kind == kind { count = count + 1 } 206 i = i + 1 207 } 208 return count 209} 210 211func nx_sb_count_by_status(b: *NxSeedBank, status: nx_int) -> nx_int { 212 if (b as i64) == 0 { return 0 } 213 var count: nx_int = 0 214 var i: nx_int = 0 215 while i < b.n_accessions { 216 let a: *NxAccession = _sb_acc_at(b, i) 217 if a.status == status { count = count + 1 } 218 i = i + 1 219 } 220 return count 221} 222 223// HHI-style concentration: returns Q10 of dominant kind's share. When 224// share >= monoculture_threshold_q10, the bank is too concentrated -- 225// diversity warning fires per the seed-bank discipline that a bank with 226// only one cultivar is a single point of failure. 227func nx_sb_audit_diversity(b: *NxSeedBank) -> nx_int { 228 if (b as i64) == 0 { return NX_SB_V_NULL } 229 if b.n_accessions == 0 { return NX_SB_V_OK_HEALTHY_DIVERSITY } 230 var max_count: nx_int = 0 231 var k: nx_int = 0 232 while k < NX_SB_KIND_N { 233 let cnt: nx_int = nx_sb_count_by_kind(b, k) 234 if cnt > max_count { max_count = cnt } 235 k = k + 1 236 } 237 let dominant_share_q10: nx_int = (max_count * NX_MAGIC_1024) / b.n_accessions 238 if dominant_share_q10 >= b.monoculture_threshold_q10 { 239 return NX_SB_V_MONOCULTURE_WARNING 240 } 241 let corrupted: nx_int = nx_sb_count_by_status(b, NX_SB_STATUS_CORRUPTED) 242 if corrupted > 0 { return NX_SB_V_CORRUPTION_DETECTED } 243 return NX_SB_V_OK_HEALTHY_DIVERSITY 244} 245 246func nx_sb_total_bytes(b: *NxSeedBank) -> nx_size { 247 if (b as i64) == 0 { return 0 } 248 var sum: nx_size = 0 249 var i: nx_int = 0 250 while i < b.n_accessions { 251 let a: *NxAccession = _sb_acc_at(b, i) 252 sum = sum + a.bytes_stored 253 i = i + 1 254 } 255 return sum 256}