d6df70ab5f
Bug: when a proxy host had per-host WAF explicitly disabled (enabled:false) with waf_mode:"merge" (or no waf_mode set), resolveEffectiveWaf entered the merge branch and returned enabled:true unconditionally, applying the global WAF to a host the user had opted out of. Fix: add `if (host.enabled === false) return null` at the top of the merge branch. Explicit opt-out now takes precedence over the global setting regardless of mode. The override mode already handled this correctly. Also extract resolveEffectiveWaf from caddy.ts into caddy-waf.ts so it can be unit tested. Add 12 new tests covering no-config fallback, merge opt-out regression, merge settings combination, and override mode. What runs without OWASP CRS: only SecRuleEngine + audit directives + any custom_directives. The @coraza.conf-recommended and CRS includes are gated behind load_owasp_crs (fixed in previous commit). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>