Surfaced during review of #196 (pre-existing; icaptcha.rs untouched by that PR). Flagging as a product decision, not a clear-cut bug.
crates/gitlawb-node/src/icaptcha.rs:302-304 — inside decide, if v.key.is_none() { return Decision::Allow; } runs before the mode match, so in Mode::Enforce a missing key (iCaptcha unreachable at startup, DNS/BGP block, bad ICAPTCHA_PUBKEY) allows every create/registration with no proof. init() (icaptcha.rs:160-166) leaves key = None and only warns. The inline comment frames this as an intentional 'stay inert' fail-safe, so this is a deliberate-vs-safe call: enforce mode silently disabling on a fetch hiccup weakens the abuse protection the node leans on after PoW removal.
Options: in enforce mode fail closed (reject) when key.is_none(), or refuse to start in enforce mode without a key; at minimum document that enforce + no-key == fail-open. Needs a maintainer decision on which. Control flow verified by execution during the #196 review.
Surfaced during review of #196 (pre-existing;
icaptcha.rsuntouched by that PR). Flagging as a product decision, not a clear-cut bug.crates/gitlawb-node/src/icaptcha.rs:302-304— insidedecide,if v.key.is_none() { return Decision::Allow; }runs before the mode match, so inMode::Enforcea missing key (iCaptcha unreachable at startup, DNS/BGP block, badICAPTCHA_PUBKEY) allows every create/registration with no proof.init()(icaptcha.rs:160-166) leaveskey = Noneand only warns. The inline comment frames this as an intentional 'stay inert' fail-safe, so this is a deliberate-vs-safe call: enforce mode silently disabling on a fetch hiccup weakens the abuse protection the node leans on after PoW removal.Options: in enforce mode fail closed (reject) when
key.is_none(), or refuse to start in enforce mode without a key; at minimum document that enforce + no-key == fail-open. Needs a maintainer decision on which. Control flow verified by execution during the #196 review.