code wiki / _hdl_build / nx_hr_bot_behavior.nx

nx_hr_bot_behavior.nx source

↩ module page · 55 lines · 4585 B

1// nx_hr_bot_behavior.nx -- NISHI HR, visitor module REDESIGNED for PRIVACY + sophistication (operator 2026-06-20: 2// "we are NOT going to log visitors / we don't want IP / we don't want anything; evaluate bots by BEHAVIOR even 3// if they are sophisticated"). SUPERSEDES the UA/IP approach (nx_hr_visitor list-match + nx_hr_visitor_log IP-log), 4// which sophisticated bots defeat (UA spoof + residential-IP rotation) AND which logs PII. This evaluates a visitor 5// purely from EPHEMERAL per-session BEHAVIOR signals -- ZERO IP / UA / identity inputs by construction (privacy by 6// design: nothing about the visitor is stored). Researcher-grounded (sovereign fetch, cited): 7// knowledge/fetched/botbehavior_scraping.raw -- web-scraping countermeasures: CAPTCHA/challenge, fingerprinting, 8// bot-detection, HONEYPOTS (invisible traps humans never touch). [en.wikipedia.org/wiki/Web_scraping] 9// knowledge/fetched/botbehavior_fingerprint.raw -- passive/behavioral fingerprinting signals. [.../Device_fingerprint] 10// knowledge/fetched/botbehavior_bot.raw -- bot taxonomy/threat. [.../Internet_bot] 11// DESIGN: no single signal (a sophisticated bot fakes any one); LAYER them + impose a cost (proof-of-work/JS 12// challenge) -- a bot can spoof a UA but cannot cheaply manufacture real human interaction entropy AND solve a 13// per-session challenge AND stay consistent. Signals are 0..100 (or 0/1), computed live by the front-end and 14// DISCARDED after the verdict. license_tier: ORIGINAL 15import "nx_syscalls.nx" 16 17const HB_ALLOW: i64 = 0 18const HB_CHALLENGE: i64 = 1 // ambiguous -> raise a cost (proof-of-work / interactive challenge), don't block a human 19const HB_BLOCK: i64 = 2 20 21// thresholds (data-driven, CLAUDE.md #11): score >= BLOCK -> block; >= CHALLENGE -> challenge; else allow. 22const HB_BLOCK_THRESH: i64 = 60 23const HB_CHALLENGE_THRESH: i64 = 30 24 25// BOT-LIKELIHOOD SCORE from ephemeral behavior signals (higher = more bot-like). NO identity inputs. 26// interaction_entropy 0..100 : richness/irregularity of mouse+scroll+timing (0 = none/linear = bot, 100 = human) 27// timing_regularity 0..100 : how machine-regular the request cadence is (100 = metronome = bot) 28// challenge_solved 0/1 : passed the per-session proof-of-work / JS challenge (0 = failed = strong bot signal) 29// sequence_anomaly 0..100 : how rigid/anomalous the navigation sequence is (100 = scripted path = bot) 30// honeypot_hit 0/1 : touched an invisible trap a human never sees (1 = near-certain bot) 31// env_consistent 0/1 : runtime behaves as the declared environment should (0 = spoof mismatch = bot) 32func hb_bot_score(interaction_entropy: i64, timing_regularity: i64, challenge_solved: i64, sequence_anomaly: i64, honeypot_hit: i64, env_consistent: i64) -> i64 { 33 var s: i64 = 0 34 if honeypot_hit == 1 { s = s + 60 } // strongest single tell (cited: honeypots) 35 if challenge_solved == 0 { s = s + 50 } // failed the cost-imposing challenge 36 var ie: i64 = interaction_entropy; if ie < 0 { ie = 0 } if ie > 100 { ie = 100 } 37 s = s + ((100 - ie) * 30) / 100 // low interaction entropy -> up to +30 38 var tr: i64 = timing_regularity; if tr < 0 { tr = 0 } if tr > 100 { tr = 100 } 39 s = s + (tr * 20) / 100 // metronomic cadence -> up to +20 40 var sa: i64 = sequence_anomaly; if sa < 0 { sa = 0 } if sa > 100 { sa = 100 } 41 s = s + (sa * 20) / 100 // scripted navigation -> up to +20 42 if env_consistent == 0 { s = s + 30 } // declared-env mismatch -> +30 43 return s 44} 45// THE VERDICT from the score (layered; CHALLENGE the ambiguous so a real human is never hard-blocked). 46func hb_verdict(score: i64) -> i64 { 47 if score >= HB_BLOCK_THRESH { return HB_BLOCK } 48 if score >= HB_CHALLENGE_THRESH { return HB_CHALLENGE } 49 return HB_ALLOW 50} 51// convenience: signals -> verdict in one call (the front desk's whole decision; stores nothing). 52func hb_evaluate(interaction_entropy: i64, timing_regularity: i64, challenge_solved: i64, sequence_anomaly: i64, honeypot_hit: i64, env_consistent: i64) -> i64 { 53 return hb_verdict(hb_bot_score(interaction_entropy, timing_regularity, challenge_solved, sequence_anomaly, honeypot_hit, env_consistent)) 54} 55func hb_verdict_name(v: i64) -> *u8 { if v == HB_BLOCK { return "BLOCK" as *u8 } if v == HB_CHALLENGE { return "CHALLENGE" as *u8 } return "ALLOW" as *u8 }