*** WebDecoy Bot Detection Changelog ***

= 2.3.3 - 2026-07-29 =
Follow-up to the 2.3.2 safety release. Four WooCommerce and reporting fixes; no behaviour change for anyone not running WooCommerce.

* Fixed (WooCommerce): the 2.3.2 card-testing fix did not apply to stores using Cash on Delivery, Direct Bank Transfer or Cheque. Those gateways never mark an order paid, so no checkout attempt was ever closed and every genuine order kept counting toward card testing and the hourly checkout limit. Whether an order was real is now decided from the order's own status, which every gateway reaches. This completes the fix promised in 2.3.2.
* Fixed (WooCommerce): a customer retrying a declined card could be mistaken for card testing on their own. Attempts are recorded per checkout submission, and WooCommerce reuses the same order across retries, so several attempts against one order looked like several attacks. The small-amount, decline-count and rapid-succession patterns now need more than one order or more than one card before they fire. Detecting several different cards from one address is unchanged.
* Fixed (WooCommerce): payment results arriving from a gateway callback — the normal case for redirect and webhook gateways — did not close the checkout attempt they belonged to, because the record was matched on the address of the callback rather than the order. Attempts stayed open and kept counting.
* Fixed: the cross-site attacker list is read again. In 2.3.2 it was collected hourly and then consulted by nothing, so a Pro site paid for the sync and got no benefit. It now answers "has this address attacked other sites?" for the CRITICAL trap notice, which previously made a live network request while rendering the page.
* Fixed: two notices claimed an attacker had been blocked network-wide, or would have been blocked on Pro. Neither is true since 2.3.2 stopped the list from blocking anything. They now say the actor is recognised, which is what actually happened.
* Fixed: the monitor-mode summary could report that nothing had met the bar for enforcement while rate limiting was being withheld on every request. Rate limiting is now included in the count.

= 2.3.2 - 2026-07-29 =
Safety release. Please update. This version deliberately makes the plugin do LESS by default.

* IMPORTANT — Monitor mode is now the default. WebDecoy detects, logs and reports everything, and blocks nothing, until you turn blocking on in Blocking > Monitor mode. Existing sites are switched to monitor mode by this update. Read the Detections page to see what enforcement would have done, then decide.
* Fixed: behind a reverse proxy (Cloudflare, a load balancer, most managed hosts) every visitor resolved to the proxy's address, because forwarding headers are correctly distrusted unless a trusted proxy is configured — and nothing detected that mismatch. One hostile request could put the proxy's address in the block list and 403 real visitors for 24 hours. The plugin now detects the condition, refuses to block while it holds, and says so in the admin.
* Fixed: `WebDecoy_Blocker::block()` validated only that a string parsed as an IP. It will no longer accept loopback, private/reserved ranges, a configured trusted proxy, or the current request's proxy front door from an automatic decision, and automatic blocks can no longer write a range wider than /24 (IPv4) or /48 (IPv6). Refusals are recorded and surfaced instead of failing silently. Blocks a human types in the admin are unaffected.
* Fixed: block expiry was written in UTC and compared against site-local time, so on any site with a UTC offset of +1 or greater a short block was already expired the moment it was written — blocking silently did nothing. All timestamps in the block table are now UTC.
* Fixed: a honeypot hit blocked the address permanently, because it was the one path that passed no duration.
* Changed: default block duration is now 1 hour, was 24. 93% of hostile addresses are gone within the hour, so a longer default caught almost nothing and mostly risked blocking whoever inherited the address next.
* Fixed (WooCommerce): completed orders counted as card-testing attempts. Three successful sub-$5.00 orders from one address in an hour — the normal profile for digital downloads, donations, tips and add-ons — were classified as an attack. Successful orders no longer count toward card-testing patterns or the checkout velocity limit. KNOWN LIMITATION: this relies on an order being marked paid, and Cash on Delivery, Direct Bank Transfer and Cheque never mark an order paid, so on a store using only those gateways the old behaviour persists. Monitor mode means it cannot cost you an order in this version; the underlying fix is tracked as issue #60.
* Changed (WooCommerce): the checkout path now refuses the order and records the detection, and never writes a sitewide IP block. Refusing the checkout is the proportionate response; blocking the whole site from a checkout false positive is not. This covers both the classic checkout and the Blocks / Store API checkout.
* Fixed: monitor mode and the kill switch now apply at EVERY point the plugin can act on a request, not just the rule engine. Previously the WooCommerce checkout, the honeytoken coupon, the challenge interstitial, login, comments and registration all still refused traffic while the admin banner said nothing was blocked — and on a WooCommerce store that could stop orders with no working way to turn it off.
* Fixed: the monitor-mode setting is now stored rather than only defaulted, so the checkbox shows the real state on an upgraded site. Before this, saving any setting silently switched full enforcement on.
* Changed: the cross-site actor feed no longer writes addresses into your block table. Measured across the network, only 2 of 4,866 addresses were ever seen at more than one site, 82% of feed entries were already a week stale and none were still active — so blocking on it mostly hit whoever holds the address now. The feed is kept as advisory intelligence. Rows it previously wrote are removed when you upgrade.
* Added: `define('WEBDECOY_DISABLE', true);` in wp-config.php stops the plugin acting on the front end, so you can always recover over FTP without database access.
* Added: admin notices that say plainly when the plugin is watching rather than acting, and why.

= 2.3.1 - 2026-07-26 =
* Fixed: Forwarded detections carry the visitor's own request signature (`cs`). The plugin beacons detections over its own HTTP connection, so the ingest service was identifying visitors by THIS SITE's outbound request headers — identical on every beacon — which collapsed every visitor a site reported into one shared "actor". Header names only, plus Accept-Language and Accept-Encoding; no header values otherwise leave the site, and proxy/CDN-injected names (cf-*, x-forwarded-*) are excluded so a visitor fingerprints consistently wherever they are seen.

= 2.3.0 - 2026-07-23 =
* Added: One-click WebDecoy Cloud connect (Settings → WebDecoy Cloud). Clicking Connect opens app.webdecoy.com to approve; on return the plugin exchanges a one-time token server-side and stores the provisioned API keys (encrypted at rest). Manual API key entry remains available under "Advanced: manual configuration".
* Added: "Send me a monthly security report" opt-in at connect time.
* Added: Plan entitlements sync (twice daily via cron) — a feature switchboard for upcoming plan-aware capabilities; any sync error fails open to the free tier.
* Fixed: Statistics page charts grew unbounded (thousands of pixels tall) once detection data existed — Chart.js canvases are now wrapped in fixed-height containers.

= 2.2.3 - 2026-07-21 =
* Changed: All CSS and JavaScript is now loaded via the WordPress dependency APIs — the challenge/block interstitials use wp_register_style/script + wp_print_styles/scripts with static asset files (public/css/, public/js/webdecoy-challenge.js), and the Statistics page attaches chart data via wp_add_inline_script. No more raw <style>/<script> tags.
* Changed: The "Protected by WebDecoy" credit on the challenge page is now an explicit admin opt-in (Settings → Blocking → Challenge Page Credit) and off by default, per WordPress.org guideline 10.
* Changed: Updated bundled Chart.js from v4.4.9 to v4.5.1 (latest stable).
* Changed: Removed load_plugin_textdomain() — unneeded since WordPress 4.6 for directory-hosted plugins (minimum is WP 6.1).
* Docs: readme now notes that good-bot documentation URLs in the bundled bot database are reference metadata only and are never requested.

= 2.2.2 - 2026-07-20 =
* Fixed: A PHP 7.4 fatal error in good-bot verification (str_ends_with is PHP 8.0+)
* Fixed: Timezone-safe date handling throughout (date() -> gmdate())
* Changed: The bundled SDK now uses the WordPress HTTP API exclusively (removed the raw cURL fallback)
* Changed: Requires WordPress 6.1+ (wp_cache_flush_group); tested up to WordPress 7.0
* Internal: Full WordPress Plugin Check compliance — resolved all 69 flagged errors

= 2.2.1 - 2026-07-19 =
* Changed: Chart.js is now bundled with the plugin instead of loaded from a CDN — no external requests for the admin charts
* Changed: Clarified the External Services disclosure in readme
* Internal: Refactored the self-hosted updater into its own module; added a WordPress.org build variant (build.sh --org) that excludes the self-updater and the cloud clearance client for directory-guideline compliance

= 2.2.0 - 2026-07-19 =
* Added: IP allowlist — IPs or CIDR ranges that bypass all detection and blocking (Settings → Blocking). Previously the check existed internally but had no way to configure it.
* Changed: Consolidated onto a single detector path (SDK detector + WordPress-signal wrapper) across front-end, forms, and WooCommerce; removed the unused legacy forms class and a dead scheduled task. No behavior change to detection.
* Added: Filter rules — write expression-based rules (e.g. `ip.tor or ip.abuse_score > 50`, `ip.country in ["CN","RU"] and req.path matches "^/wp-login"`) evaluated before scoring; block or throttle, with dry-run. New Settings → Rules tab with a rule builder and parse-on-save validation. Expression language is byte-for-byte compatible with @webdecoy/node.
* Added: IP enrichment — VPN/proxy/Tor, geo, ASN, and abuse-score data (WebDecoy Cloud) powering the ip.* filter-rule fields, cached 1 hour, fetched only when a rule needs it, fail-open.
* Improved: Rate limiting now runs as a rule in the engine — over-limit requests get a proper 429 with Retry-After and X-RateLimit-* headers (previously it only nudged the bot score). Adds a sliding-window algorithm (exact via a persistent object cache, falling back to the fixed-window database counter), per-IP / per-IP+route / per-user keying, and dry-run.
* Added: Stealth-browser detection (F1) — catches scrapers that patch native browser functions to hide automation (puppeteer-extra-stealth, botasaurus, etc.), the class of tool that defeats conventional fingerprinting. Strong tells (patched Function.prototype.toString, a modified navigator.webdriver getter) are decisive; weak tells that real privacy extensions can trigger are scored gently so they never block a legitimate visitor.
* Added: Clearance client — bundled @webdecoy/client browser script that silently mints a wd_clearance cookie for real visitors (idle-deferred, once per session, no proof-of-work). Enables tripwire/decoy hits to durably lock out the offending device. Configured via a new publishable Site Key in the WebDecoy Cloud tab.
* Added: Rule engine — deterministic rules evaluated before heuristic scoring; first DENY/THROTTLE wins, with dry-run (log without blocking). Parity with @webdecoy/node.
* Added: Tripwires (deception layer) — deterministic, zero-false-positive blocking of hidden honeypot paths (scanner-bait like /.env, /.git/config, /wp-config.php). On by default. Custom exact paths, prefixes, and regex patterns; block or throttle; dry-run. New Settings → Tripwires tab.
* Added: Honeytoken — automatically injects an invisible decoy link on front-end pages pointing at a secret per-site path; only link-following scrapers ever request it, and a hit is armed as a tripwire. On by default, with optional daily rotation. Never shown to real visitors or logged-in users.
* Added: WooCommerce honeytoken coupons — a hidden decoy promo code is planted on cart/checkout pages where coupon-scraping bots look but no human ever sees it. Applying it (classic checkout or Blocks/Store API) is a deterministic bot signal: recorded and, per your blocking setting, blocked. Optional daily rotation with a grace window; real coupons and shoppers are never affected.
* Added: WordPress-native traps — fake vulnerable-plugin paths (armed only for plugins not actually installed, so real plugins are never shadowed), optional XML-RPC probing trap (off by default), and author-enumeration protection: ?author=N and REST user enumeration return a canary username instead of leaking real ones, and a later login attempt with that canary is flagged as a critical exfiltration detection.
* Added: Deceptive tripwire responses — a tripwire hit can serve a 404, believable fake content (fake .env / wp-config / SQL dump / phpinfo seeded with unique per-site canary credentials), or a slow-drip tarpit, instead of a plain 403. A later login attempt using a canary credential is logged as a critical exfiltration detection and blocked. Decoy content is template-only and never exposes real configuration.
* Added: wd_clearance forwarding — a tripwire hit carrying the visitor's wd_clearance cookie is reported so the WebDecoy Cloud can durably deny the actor's device fingerprint (rotation-proof lockout). Heuristic rules never carry the token.
* Added: Violation reporting — rule hits are reported to the WebDecoy Cloud (premium), spooled to a local queue and delivered on request shutdown (after the response is handed back, so no added page latency). Survives brief ingest outages: retried once by a cron safety net, then dropped, with a hard queue cap. Hits are always recorded locally in the Detections page.
* Added: JS execution verification — detects non-JS HTTP scrapers (e.g., Scrapling Fetcher, curl_cffi)
* Added: Challenge token meta tag injected on page serve for premium users
* Added: Automatic page serve reporting to ingest service

= 2.0.0 - 2026-03-01 =
* Major: All detection and protection now works locally — no API key required
* Added: Invisible proof-of-work (PoW) challenge system (SHA-256, no external service)
* Added: Behavioral scoring for form submissions
* Added: Statistics page with Chart.js detection trend charts
* Added: Enhanced detections page with date filters, CSV export, bulk actions
* Added: WebDecoy Cloud tab (optional premium features)
* Improved: Settings page restructured — Protection tab is now first
* Improved: Dashboard widget with subtle cloud upsell
* Fixed: PHP 7.4 compatibility maintained
* Changed: CDN update checker only active with WEBDECOY_SELF_HOSTED constant
* Changed: Version bump to 2.0.0 signaling architecture change

2026-01-09 - version 1.3.8
* Fixed - Removed no_plugins trigger (deprecated in modern browsers, caused false positives)

2025-12-13 - version 1.3.7
* Update - Version bump

2025-12-10 - version 1.3.6
* Fixed - Protection hooks only activate when API key is validated as active
* Fixed - E2E test compatibility - plugin now properly detects unconfigured state
* Update - Form and WooCommerce protection requires active API connection

2025-12-09 - version 1.3.5
* Added - Security improvements and code hardening
* Update - WooCommerce compatibility to 9.4
* Fixed - Performance optimizations for detection checks

2025-12-01 - version 1.3.4
* Fixed - SDK loading path resolution
* Fixed - Error handling for API connections
* Fixed - Rate limiter reliability improvements

2025-11-15 - version 1.3.3
* Added - Support for custom block page templates
* Fixed - IP blocking with automatic expiration
* Fixed - Proxy headers handling (X-Forwarded-For)

2025-11-01 - version 1.3.2
* Update - WooCommerce High-Performance Order Storage (HPOS) compatibility
* Fixed - Carding protection detection accuracy
* Fixed - Dashboard widget display issues

2025-10-15 - version 1.3.1
* Added - Detection export functionality
* Fixed - Admin UI responsiveness
* Fixed - Timezone handling in detection logs

2025-10-01 - version 1.3.0
* Added - Bulk IP blocking/unblocking
* Added - Enhanced good bot detection (60+ bots)
* Update - Major performance improvements
* Fixed - WooCommerce checkout protection

2025-09-01 - version 1.2.0
* Added - VPN/Proxy detection capabilities
* Added - AI crawler blocking options (GPTBot, ClaudeBot)
* Update - Enhanced browser fingerprinting
* Fixed - Rate limiting algorithm improvements

2025-08-01 - version 1.1.0
* Added - WebRTC IP leak detection for VPN/proxy detection
* Added - Geographic consistency checks (timezone, language mismatch)
* Update - Bot detection with parallel async checks
* Fixed - Fingerprinting improvements

2025-07-01 - version 1.0.0
* Added - Initial release
* Added - Server-side bot detection
* Added - Client-side browser fingerprinting
* Added - Comment, login, and registration protection
* Added - WooCommerce carding protection
* Added - Honeypot field injection
* Added - Rate limiting
* Added - IP blocking with expiration
* Added - Good bot allowlist (60+ bots)
* Added - AI crawler detection
* Added - Centralized WebDecoy integration
* Added - Dashboard widget
* Added - Detection logging and export
