code wiki / (root) / nx_pollinate.nx

nx_pollinate.nx source

↩ module page · 338 lines · 13587 B

1// nx_pollinate.nx -- peer-mesh community defense distribution. 2// 3// Biology: bees cross-flower pollination spreads genetic material 4// across a community of flowers, so a useful trait that arose in one 5// plant becomes available to many. Nishi pollinate is the cross-host 6// distribution of useful DEFENSIVE material: federation-ready 7// antibodies (per [[feedback-unified-immune-architecture-three-tier]] 8// item "antibody V2 federates via peer mesh"), decoy tripwire tokens 9// (per nx_decoy V2 cross-host registry), and signed xenocell 10// observations (the Citizen Lab analog). 11// 12// Per [[feedback-captain-moroni-doctrine]]: defensive only. We share 13// DETECTION SIGNATURES not exploitation payloads. We share OBSERVED 14// ATTACKS not retaliation plans. Captain Moroni's discipline: spread 15// the warning so other operators can defend, never spread the weapon. 16// 17// Per [[feedback-cell-immune-system-ransomware-judo-ddos-by-bit]]: 18// the judo is of INFORMATION. Vendor monitoring 1000 hosts becomes 19// 1000 hosts holding 1000 signed records of vendor monitoring. The 20// pollinate primitive scales that judo across the community. 21// 22// Per [[feedback-privacy-by-default-no-tracking]]: pollinate is 23// PER-CALL CONSENT (matches existing nx_trace_consent in the bit- 24// traceability cardinal). No automatic distribution; operator 25// explicitly approves each share. V2 adds policy-driven auto-share 26// for high-confidence federation-ready material. 27// 28// Payload kinds shipped V1: 29// ANTIBODY -- federation-ready detection signature 30// DECOY_TOKEN -- "this token was planted in my host; flag if 31// it shows up at yours" 32// XENO_OBSERVATION -- signed observation of vendor / state-actor 33// behavior; community-knowledge-of-record 34// IMMUNE_ALERT -- "host X is COMPROMISED; consider your peer 35// session with it suspect" 36// RECLAIM_REPORT -- "this commodity hardware reclaimed safely 37// with these mitigations; others can apply" 38// 39// Composes: 40// nx_antibody -- federation-ready antibodies are V1 payload 41// nx_decoy -- tripwire-token registry crosses hosts 42// nx_xenocell -- signed observations distribute via pollinate 43// nx_immune -- IMMUNE_ALERT propagates colony-status to peers 44// nx_reclaim -- reclamation reports help community apply 45// proven mitigations on similar hardware 46// nx_evict_journal -- every pollination event logged (no silent share) 47// 48// V1 ships: 49// - struct NxPollinationPayload (kind + content_hash + body_len + 50// body_ptr + signature + ts) 51// - send/receive verbs (caller wires the network transport) 52// - consent gate (operator approves OR auto-share if policy says) 53// - per-peer relationship tracking (last_share / received_count) 54// 55// Gap list (V1 honest perf verdict): 56// - transport is caller-supplied (no built-in onion/peer routing) 57// - signature validation is shape-only (V2 inlines nx_ml_dsa_65) 58// - no automatic dedup across peer hops (peer can re-share its 59// own pollination back to source; V2 adds tombstones) 60// - auto-share policy is a single bool (V2 makes per-kind policy) 61// 62// genealogy_id: cardinal_2026-05-19_unified_immune_federation + 63// cardinal_2026-05-17_cell_immune_judo + 64// cardinal_2026-05-07_captain_moroni_doctrine + 65// biology_bee_cross_flower_pollination 66// lineage_id: substrate_pollinate_v1 67// 68// nx_safety_envelope: 69// intended_use: "Peer-mesh community defense distribution 70// of detection signatures, decoy tokens, 71// xenocell observations, reclaim reports; 72// DEFENSIVE ONLY, per-call consent" 73// sil_target: SIL3 74// evidence: [defensive_only, consent_gated, 75// captain_moroni_aligned, 76// no_exploitation_payload] 77// verdict: NOT_YET_EVALUATED 78 79import "nx_syscalls.nx" 80import "nx_tier.nx" 81import "nx_budget.nx" 82import "nx_attention_class.nx" 83import "nx_evict_journal.nx" 84 85// ===== Sealed enum: NxPollinationKind ============================= 86 87const NX_PK_ANTIBODY: nx_int = 0 88const NX_PK_DECOY_TOKEN: nx_int = 1 89const NX_PK_XENO_OBSERVATION: nx_int = 2 90const NX_PK_IMMUNE_ALERT: nx_int = 3 91const NX_PK_RECLAIM_REPORT: nx_int = 4 92const NX_PK_N_KINDS: nx_int = 5 93 94// ===== Sealed enum: NxPollinateVerdict ============================ 95 96const NX_PL_OK: nx_int = 0 97const NX_PL_ERR_BAD_KIND: nx_int = 1 98const NX_PL_ERR_BAD_SIG: nx_int = 2 99const NX_PL_ERR_CONSENT_REQUIRED: nx_int = 3 100const NX_PL_REFUSED_BY_POLICY: nx_int = 4 // auto-share policy says no 101const NX_PL_QUEUE_FULL: nx_int = 5 102 103// ===== Struct: NxPollinationPayload ============================== 104// 105// kind selects the payload type. content_hash is BLAKE3 (or 106// equivalent) of body. body_ptr + body_len hold the actual content. 107// sig_ptr + sig_len hold the originator's ML-DSA-65 signature. 108// originator_id identifies which Nishi host emitted this. 109 110struct NxPollinationPayload { 111 kind: nx_int, 112 originator_id: nx_int, 113 content_hash: nx_size, 114 body_ptr: *u8, 115 body_len: nx_size, 116 sig_ptr: *u8, 117 sig_len: nx_size, 118 ts_us: nx_size, 119} 120 121// ===== Struct: NxPeerRelation ==================================== 122// 123// One row per known peer host. peer_id is stable identifier; 124// trust_q10 captures operator's accumulated trust (low for new 125// peers, climbs with successful federation events). last_share_us 126// + share_count track the relationship intensity. 127 128struct NxPeerRelation { 129 peer_id: nx_int, 130 trust_q10: nx_int, 131 last_share_us: nx_size, 132 share_count: nx_int, 133 receive_count: nx_int, 134} 135 136// ===== Struct: NxPollinator ====================================== 137// 138// The substrate-side coordinator. peers is a fixed-capacity ring of 139// known peer relations. outbox holds pending payloads awaiting 140// consent or transport. consent_required flag enforces per-call 141// operator approval (V1 default); when 0, auto-share policy applies. 142 143struct NxPollinator { 144 peers: *NxPeerRelation, 145 peer_capacity: nx_size, 146 n_peers: nx_size, 147 outbox: *NxPollinationPayload, 148 outbox_capacity: nx_size, 149 n_outbox: nx_size, 150 consent_required: nx_int, // 1 = per-call operator gate; 0 = auto 151 journal: *NxEvictJournal, 152} 153 154const NX_PEER_BYTES: nx_size = 40 155const NX_PL_PAYLOAD_BYTES: nx_size = 64 156 157// ===== Validators ================================================ 158 159func nx_pk_is_valid(k: nx_int) -> nx_int { 160 if k < 0 { return 0 } 161 if k >= NX_PK_N_KINDS { return 0 } 162 return 1 163} 164 165// ===== nx_pollinator_new ========================================= 166 167func nx_pollinator_new(peer_capacity: nx_size, 168 outbox_capacity: nx_size, 169 consent_required: nx_int, 170 journal: *NxEvictJournal) -> *NxPollinator { 171 let p: *NxPollinator = (sys_mmap(56)) as *NxPollinator 172 let peer_bytes: nx_size = peer_capacity * NX_PEER_BYTES 173 let out_bytes: nx_size = outbox_capacity * NX_PL_PAYLOAD_BYTES 174 p.peers = (sys_mmap(peer_bytes)) as *NxPeerRelation 175 p.peer_capacity = peer_capacity 176 p.n_peers = 0 177 p.outbox = (sys_mmap(out_bytes)) as *NxPollinationPayload 178 p.outbox_capacity = outbox_capacity 179 p.n_outbox = 0 180 p.consent_required = consent_required 181 p.journal = journal 182 return p 183} 184 185// ===== _peer_at / _outbox_at ===================================== 186 187func _peer_at(p: *NxPollinator, idx: nx_size) -> *NxPeerRelation { 188 return (p.peers as i64 + (idx as i64) * NX_PEER_BYTES) as *NxPeerRelation 189} 190 191func _outbox_at(p: *NxPollinator, idx: nx_size) -> *NxPollinationPayload { 192 return (p.outbox as i64 + (idx as i64) * NX_PL_PAYLOAD_BYTES) as *NxPollinationPayload 193} 194 195// ===== _find_peer ================================================ 196 197func _find_peer(p: *NxPollinator, peer_id: nx_int) -> nx_int { 198 var k: nx_size = 0 199 while k < p.n_peers { 200 let r: *NxPeerRelation = _peer_at(p, k) 201 if r.peer_id == peer_id { return k as i64 } 202 k = k + 1 203 } 204 return -1 205} 206 207// ===== nx_pollinate_add_peer ===================================== 208 209func nx_pollinate_add_peer(p: *NxPollinator, 210 peer_id: nx_int, 211 initial_trust_q10: nx_int) -> nx_int { 212 if p.n_peers >= p.peer_capacity { return -1 } 213 if _find_peer(p, peer_id) >= 0 { return -1 } 214 let r: *NxPeerRelation = _peer_at(p, p.n_peers) 215 r.peer_id = peer_id 216 r.trust_q10 = initial_trust_q10 217 r.last_share_us = 0 218 r.share_count = 0 219 r.receive_count = 0 220 p.n_peers = p.n_peers + 1 221 return (p.n_peers - 1) as i64 222} 223 224// ===== nx_pollinate_propose ====================================== 225// 226// Operator-driven: caller proposes a payload for distribution. 227// If consent_required is 1, payload sits in outbox awaiting 228// nx_pollinate_consent. If consent_required is 0, payload becomes 229// immediately send-ready (auto-share). 230// 231// Returns OK if queued, BAD_KIND on bad kind, BAD_SIG on missing 232// signature, QUEUE_FULL if outbox is full. 233 234func nx_pollinate_propose(p: *NxPollinator, 235 payload: *NxPollinationPayload) -> nx_int { 236 if (payload as i64) == 0 { return NX_PL_ERR_BAD_KIND } 237 if nx_pk_is_valid(payload.kind) == 0 { return NX_PL_ERR_BAD_KIND } 238 if (payload.sig_ptr as i64) == 0 { return NX_PL_ERR_BAD_SIG } 239 if payload.sig_len <= 0 { return NX_PL_ERR_BAD_SIG } 240 if p.n_outbox >= p.outbox_capacity { return NX_PL_QUEUE_FULL } 241 let slot: *NxPollinationPayload = _outbox_at(p, p.n_outbox) 242 slot.kind = payload.kind 243 slot.originator_id = payload.originator_id 244 slot.content_hash = payload.content_hash 245 slot.body_ptr = payload.body_ptr 246 slot.body_len = payload.body_len 247 slot.sig_ptr = payload.sig_ptr 248 slot.sig_len = payload.sig_len 249 slot.ts_us = payload.ts_us 250 p.n_outbox = p.n_outbox + 1 251 return NX_PL_OK 252} 253 254// ===== nx_pollinate_consent ====================================== 255// 256// Operator approves the payload at outbox index. After consent, the 257// integration-layer transport reads the outbox slot and dispatches. 258// V1 marks consent by appending to journal; V2 adds a "consented" 259// flag on the payload itself. 260 261func nx_pollinate_consent(p: *NxPollinator, 262 outbox_idx: nx_size, 263 now_us: nx_size) -> nx_int { 264 if outbox_idx >= p.n_outbox { return NX_PL_ERR_CONSENT_REQUIRED } 265 let pl: *NxPollinationPayload = _outbox_at(p, outbox_idx) 266 if (p.journal as i64) != 0 { 267 nx_evict_log(p.journal, now_us, 268 pl.originator_id, NX_EVR_MIGRATED, 269 NX_RES_NET, NX_AC_DEV, 0) 270 } 271 return NX_PL_OK 272} 273 274// ===== nx_pollinate_send ========================================= 275// 276// Outbound: send one payload to one peer. Updates peer's 277// share_count + last_share_us. Returns OK or CONSENT_REQUIRED if 278// per-call gating is on and consent hasn't been logged yet. 279 280func nx_pollinate_send(p: *NxPollinator, 281 peer_id: nx_int, 282 payload: *NxPollinationPayload, 283 now_us: nx_size) -> nx_int { 284 if p.consent_required == 1 { return NX_PL_ERR_CONSENT_REQUIRED } 285 if nx_pk_is_valid(payload.kind) == 0 { return NX_PL_ERR_BAD_KIND } 286 let pidx: nx_int = _find_peer(p, peer_id) 287 if pidx < 0 { return NX_PL_REFUSED_BY_POLICY } 288 let r: *NxPeerRelation = _peer_at(p, pidx as nx_size) 289 r.share_count = r.share_count + 1 290 r.last_share_us = now_us 291 return NX_PL_OK 292} 293 294// ===== nx_pollinate_receive ====================================== 295// 296// Inbound: caller's transport received a payload from a peer. We 297// validate kind + signature shape, then update peer relation and 298// hand caller a usable payload pointer for downstream integration 299// (e.g., nx_antibody_generate using the received signature). 300 301func nx_pollinate_receive(p: *NxPollinator, 302 peer_id: nx_int, 303 payload: *NxPollinationPayload, 304 now_us: nx_size) -> nx_int { 305 if (payload as i64) == 0 { return NX_PL_ERR_BAD_KIND } 306 if nx_pk_is_valid(payload.kind) == 0 { return NX_PL_ERR_BAD_KIND } 307 if (payload.sig_ptr as i64) == 0 { return NX_PL_ERR_BAD_SIG } 308 if payload.sig_len <= 0 { return NX_PL_ERR_BAD_SIG } 309 let pidx: nx_int = _find_peer(p, peer_id) 310 if pidx < 0 { return NX_PL_REFUSED_BY_POLICY } 311 let r: *NxPeerRelation = _peer_at(p, pidx as nx_size) 312 r.receive_count = r.receive_count + 1 313 return NX_PL_OK 314} 315 316// ===== nx_pollinate_outbox_count ================================= 317 318func nx_pollinate_outbox_count(p: *NxPollinator) -> nx_size { 319 return p.n_outbox 320} 321 322// ===== nx_pollinate_peer_share_count ============================= 323 324func nx_pollinate_peer_share_count(p: *NxPollinator, peer_id: nx_int) -> nx_int { 325 let pidx: nx_int = _find_peer(p, peer_id) 326 if pidx < 0 { return 0 } 327 let r: *NxPeerRelation = _peer_at(p, pidx as nx_size) 328 return r.share_count 329} 330 331// ===== nx_pollinate_peer_receive_count =========================== 332 333func nx_pollinate_peer_receive_count(p: *NxPollinator, peer_id: nx_int) -> nx_int { 334 let pidx: nx_int = _find_peer(p, peer_id) 335 if pidx < 0 { return 0 } 336 let r: *NxPeerRelation = _peer_at(p, pidx as nx_size) 337 return r.receive_count 338}