=== Bedrock Shield ===
Contributors: bedrockdigital
Tags: security, firewall, malware scanner, brute force, waf, hardening, alerts
Requires at least: 5.8
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

WordPress protection that turns on with the defaults. Firewall, login lockouts, and a daily scan. No DNS change.

== Description ==

Bedrock Shield is for people who built a WordPress site and want protection without hiring an agency or changing nameservers. Activate it. Leave the defaults on. You never change DNS.

It is a single-folder, dependency-free plugin. The request firewall, login lockouts, and scanner start on. Two-factor is optional until you enroll on your Profile. Connect a Hub plan (Basic, Pro, or Shield Care) if you just bought one. A local or own site can stay unlinked and keep these features on.

What it covers:

* **Request firewall (WAF).** Inspects query strings, cookies, the request URI, and front-end POST bodies for SQL injection, XSS, path traversal, LFI/RFI wrappers, and code-execution / webshell markers. Blocks or runs in monitor-only mode.
* **Login protection.** Per-IP brute-force lockouts, blocking of common usernames, generic login errors, and an optional hidden login URL.
* **Endpoint hardening.** Neutralizes XML-RPC pingback/multicall amplification, blocks REST `/wp/v2/users` enumeration and `?author=` scans, and strips discovery headers.
* **Rate limiting / flood control.** Throttles wp-login, xmlrpc, REST, and admin-ajax, and blocks 404 floods from vulnerability scanners.
* **Malware & integrity scanner.** Daily and on-demand scan for webshell signatures, executable PHP in uploads, newly-planted must-use plugins, and core files that fail the official checksum.
* **Post-exploit monitor.** Alerts on new administrators, role escalation, plugin/theme activation, and critical option changes (siteurl/home hijack, opened registration, admin-email change).
* **Site hardening.** Hides the WordPress version, sends security headers, disables the dashboard file editor, and blocks requests to sensitive files.
* **Centralized alerting.** Email and/or signed webhook (Slack or generic JSON) so one inbox can watch this site, or a few sites from the Hub.

Bedrock Shield is application-layer defense. Keep WordPress and plugins updated. Use the included server snippets for static files PHP never sees. An edge CDN or Cloudflare is optional and advanced. It is not required, and it needs a nameserver or CNAME change if you choose it later.

== Installation ==

1. Upload the `bedrock-shield` folder to `/wp-content/plugins/` (or install the ZIP via Plugins, Add New, Upload Plugin).
2. Activate through the Plugins menu. Defaults are on. You do not change DNS.
3. Open **Bedrock Shield**. Follow Your first 10 minutes: leave Protect on, run a first scan, and connect a Hub plan if you just bought one.
4. Two-factor is optional. Enroll from your Profile when you want it.
5. See `INSTALL.md` for the optional must-use loader and the `.htaccess` / nginx snippets.

== Changelog ==

= 2.1.175 =
* New - A hash_check restore that lists no file hashes refuses extracted files. A bound restore refuses extracted files that are not in the listed hashes. A hash_check restore that lists a SQL dump must keep db.sha256. A bound restore still checks listed db size even without db.sha256. A bound restore that lists db.sha256 must keep hash_check. A 2.1.114 bind that lists file hashes must still cover that inventory. A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.174 =
* New - A bound restore refuses extracted files that are not in the listed hashes. A hash_check restore that lists a SQL dump must keep db.sha256. A bound restore still checks listed db size even without db.sha256. A bound restore that lists db.sha256 must keep hash_check. A 2.1.114 bind that lists file hashes must still cover that inventory. A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.173 =
* New - A hash_check restore that lists a SQL dump must keep db.sha256. A bound restore still checks listed db size even without db.sha256. A bound restore that lists db.sha256 must keep hash_check. A 2.1.114 bind that lists file hashes must still cover that inventory. A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.172 =
* New - A bound restore still checks listed db size even without db.sha256. A bound restore that lists db.sha256 must keep hash_check. A 2.1.114 bind that lists file hashes must still cover that inventory. A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.171 =
* New - A bound restore that lists db.sha256 must keep hash_check. A 2.1.114 bind that lists file hashes must still cover that inventory. A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. A Hub operator password rotate still needs the Hub operator password and shares the operator password burst before the password check. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the operator billing burst before the password check. A Hub Extra enable or disconnect still needs the Hub password and shares the Extra burst before the password check. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.170 =
* New - A 2.1.114 bind that lists file hashes must still cover that inventory. A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. A Hub operator password rotate still needs the Hub operator password and shares the operator password burst before the password check. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the operator billing burst before the password check. A Hub Extra enable or disconnect still needs the Hub password and shares the Extra burst before the password check. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.169 =
* New - A restore with a bind still checks listed file hashes even without hash_check. A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. A Hub operator password rotate still needs the Hub operator password and shares the operator password burst before the password check. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the operator billing burst before the password check. A Hub Extra enable or disconnect still needs the Hub password and shares the Extra burst before the password check. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.168 =
* New - A restore archive that names this Site ID must keep its bind. Archives without a Site ID still restore. A Hub operator password rotate still needs the Hub operator password and shares the operator password burst before the password check. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the operator billing burst before the password check. A Hub Extra enable or disconnect still needs the Hub password and shares the Extra burst before the password check. Saving or removing bucket keys still needs the Hub password and shares the bucket burst. A Cloudflare token save or disconnect still needs the Hub password and shares the Cloud token burst. A Site key rotate still needs the Hub password and shares the rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.167 =
* New - A Hub operator password rotate still needs the Hub operator password, is listed under Account activity, and shares the eight-try operator password burst before the password check. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the operator billing burst before the password check. A Hub Extra enable or disconnect still needs the Hub password and shares the Extra burst before the password check. Saving or removing bucket keys still needs the Hub password and shares the bucket burst. A Cloudflare token save or disconnect still needs the Hub password and shares the Cloud token burst. A Site key rotate still needs the Hub password and shares the rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.166 =
* New - A Hub operator Extra enable or disconnect still needs the Hub operator password, is listed under Account activity, and shares the eight-try operator billing burst before the password check. A Hub Extra enable or disconnect still needs the Hub password and shares the Extra burst before the password check. Saving or removing bucket keys still needs the Hub password and shares the bucket burst. A Cloudflare token save or disconnect still needs the Hub password and shares the Cloud token burst. A Site key rotate still needs the Hub password and shares the rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.165 =
* New - A Hub Extra enable or disconnect still needs the Hub password, is listed under Account activity, and shares the eight-try Extra burst before the password check. Saving or removing bucket keys still needs the Hub password and shares the bucket burst. A Cloudflare token save or disconnect still needs the Hub password and shares the Cloud token burst. A Site key rotate still needs the Hub password and shares the rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.164 =
* New - Saving or removing bucket keys still needs the Hub password, is listed under Account activity, and shares the eight-try bucket burst. A Cloudflare token save or disconnect still needs the Hub password and shares the Cloud token burst. A Site key rotate still needs the Hub password and shares the rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.163 =
* New - A Cloudflare token save or disconnect still needs the Hub password, is listed under Account activity, and shares the eight-try Cloud token burst. A Site key rotate still needs the Hub password and shares the rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.162 =
* New - A Site key rotate still needs the Hub password, is listed under Account activity, and shares the eight-try rotate burst. A Site disconnect still needs the Hub password and shares the disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.161 =
* New - A Site disconnect still needs the Hub password, is listed under Account activity, and shares the eight-try disconnect burst. Signing out one device, other devices, or all devices still needs the Hub password and shares the session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.160 =
* New - Signing out one device, other devices, or all devices still needs the Hub password, is listed under Account activity, and shares the eight-try session burst. Hub two-factor start, finish, or disable still needs the Hub password or authenticator code and shares the two-factor burst. Plan writes stay password-gated. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.159 =
* New - A Hub two-factor start, finish, or disable still needs the Hub password or authenticator code, is listed under Account activity, and shares the eight-try two-factor burst. Plan cancel, resume, switch, or close still need the Hub password and share the plan burst. Buy more seats stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.158 =
* New - A plan cancel, resume, switch, or close still needs the Hub password, is listed under Account activity, and shares the eight-try plan burst. Buy more seats stays a click. Remove selected sites still needs the Hub password and shares the seat burst. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.157 =
* New - Removing selected sites still needs the Hub password, is listed under Account activity, and shares the eight-try seat burst. Buy more seats stays a click. Extra Show stays passwordless. GET Cloud still refreshes bound-zone ruleset status and is refused after eight tries in 15 minutes. A Hub Extra refresh from Hub support is listed under Account activity. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.156 =
* New - Buying more seats stays a click, is listed under Account activity, and is refused after eight tries in 15 minutes. Extra Show stays passwordless. GET Cloud still refreshes bound-zone ruleset status and is refused after eight tries in 15 minutes. A Hub Extra refresh from Hub support is listed under Account activity. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.155 =
* New - GET Cloud still refreshes bound-zone ruleset status and is refused after eight tries in 15 minutes. Extra Show stays passwordless. A Hub Extra refresh from Hub support is listed under Account activity. A Hub Extra enable or disconnect from Hub support is listed under Account activity. A Hub virtual-patch validate stays a click and shares the eight-try virtual-patch burst. A Hub operator password rotate still needs the Hub operator password and shares the eight-try operator password burst. A Hub Extra enable or disconnect still needs the Hub password and shares the eight-try Extra burst. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.154 =
* New - A Hub Extra refresh from Hub support is listed under Account activity. Extra Show stays passwordless. A Hub Extra enable or disconnect from Hub support is listed under Account activity. A Hub virtual-patch validate stays a click and shares the eight-try virtual-patch burst. A Hub operator password rotate still needs the Hub operator password and shares the eight-try operator password burst. A Hub Extra enable or disconnect still needs the Hub password and shares the eight-try Extra burst. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the eight-try operator billing burst. Extra Show stays passwordless. A Hub operator billing portal or export stays a click and shares the eight-try operator billing burst. A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.153 =
* New - A Hub Extra enable or disconnect from Hub support is listed under Account activity. Extra Show stays passwordless. A Hub virtual-patch validate stays a click and shares the eight-try virtual-patch burst. A Hub operator password rotate still needs the Hub operator password and shares the eight-try operator password burst. A Hub Extra enable or disconnect still needs the Hub password and shares the eight-try Extra burst. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the eight-try operator billing burst. Extra Show stays passwordless. A Hub operator billing portal or export stays a click and shares the eight-try operator billing burst. A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.152 =
* New - A Hub virtual-patch validate stays a click and shares the eight-try virtual-patch burst. A Hub operator password rotate still needs the Hub operator password and shares the eight-try operator password burst. A Hub Extra enable or disconnect still needs the Hub password and shares the eight-try Extra burst. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the eight-try operator billing burst. Extra Show stays passwordless. A Hub operator billing portal or export stays a click and shares the eight-try operator billing burst. A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.151 =
* New - A Hub operator password rotate still needs the Hub operator password and shares the eight-try operator password burst. A Hub Extra enable or disconnect still needs the Hub password and shares the eight-try Extra burst. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the eight-try operator billing burst. Extra Show stays passwordless. A Hub operator billing portal or export stays a click and shares the eight-try operator billing burst. A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.150 =
* New - A Hub Extra enable or disconnect still needs the Hub password and shares the eight-try Extra burst. A Hub operator Extra enable or disconnect still needs the Hub operator password and shares the eight-try operator billing burst. Extra Show stays passwordless. A Hub operator billing portal or export stays a click and shares the eight-try operator billing burst. A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.149 =
* New - A Hub operator billing portal or export stays a click and shares the eight-try operator billing burst. Extra Show stays passwordless. A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.148 =
* New - A Hub site rotate or license override stays a click and shares the eight-try operator console burst. A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.147 =
* New - A Hub Care claim, start, or complete stays a click and shares the eight-try Care queue burst. Care operator reveal stays passwordless and stays on the reveal burst. A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.146 =
* New - A Hub virtual-patch stage, publish, or rollback stays a click and shares the eight-try virtual-patch burst. Fleet virtual-patch writes stay hidden. A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.145 =
* New - A Hub support connect or reset email stays a click and shares the eight-try support burst. Staff notes stay hidden and share the support burst. Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.144 =
* New - Extra is available when Extra is configured. Extra Show stays passwordless. A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.143 =
* New - A Shield Care cleanup fee is listed under Account activity. A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.142 =
* New - A sites, activity, billing, or Care handoff CSV downloaded from Hub support is listed under Account activity. A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.141 =
* New - A site suspend, complimentary Pro, or override clear from Hub support is listed under Account activity. A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.140 =
* New - A connect or sign-in email from Hub support is listed under Account activity. A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.139 =
* New - A Site key rotate, restore, or revoke from Hub support is listed under Account activity. A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.138 =
* New - A password reset email is listed under Account activity. Requesting a password reset stays a click. Site keys revoked after a password or 2FA change are listed under Account activity. Saving a Care follow-up note or site details stays a click. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.137 =
* New - A Care follow-up note or site details save is listed under Account activity. Saving a Care follow-up note or site details stays a click and refuses a ninth try in 15 minutes. Saving or removing Care WordPress access stays a click. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.136 =
* New - A Care WordPress access save or revoke is listed under Account activity. Saving or removing Care WordPress access stays a click and refuses a ninth try in 15 minutes. Saving email preferences stays a click. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.135 =
* New - Saving email preferences stays a click and refuses a ninth try in 15 minutes. A weekly summary or setup reminder change is listed under Account activity. A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.134 =
* New - A Hub sign-in lockout is listed under Account activity. Saving a site label stays a click. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.133 =
* New - A site label save is listed under Account activity. Saving a site label stays a click and refuses a ninth try in 15 minutes. Opening Manage billing stays a click. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.132 =
* New - A billing portal open is listed under Account activity. Opening Manage billing stays a click and refuses a ninth try in 15 minutes. Export downloads stay a click. Protect settings save stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.131 =
* New - A sites, activity, billing, or Care handoff CSV is listed under Account activity. Export downloads stay a click and refuse a ninth try in 15 minutes. Protect settings save stays a click. Guided lockdown, admin two-factor, virtual-patch raise, and login tighten stay a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.130 =
* New - Protect settings save stays a click and shares the eight-try Protect burst. Guided lockdown, admin two-factor, virtual-patch raise, and login tighten stay a click and share the Protect burst. Watch alert settings stay a click. Preview restore stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.129 =
* New - Watch alert settings stay a click and share the eight-try Watch burst. A restore preview is listed under Account activity. Preview restore stays a click and refuses a ninth try in 15 minutes. Watch URL, Check now, and Send test stay a click. A backup download stays a click. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.128 =
* New - A Watch URL save, a Watch check, a Watch test, and Watch alert settings are listed under Account activity. Watch URL, Check now, and Send test stay a click and refuse a ninth try in 15 minutes. A backup download stays a click and refuses a ninth try in 15 minutes. Setup reminder changes are listed under Account activity. A Copy now or restore stays listed. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.127 =
* New - A Copy now or restore is listed under Account activity. Copy now and restore stay a click and refuse a ninth try in 15 minutes. Turning Extra protection on or off is listed under Account activity. A Site disconnect is listed under Account activity. A backup download stays listed. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.126 =
* New - Saving or removing bucket keys is listed under Account activity. A backup download is listed under Account activity. Saving or removing bucket keys still needs the Hub password. A Cloudflare token Show and a bucket key Show stay listed. Load zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.125 =
* New - A Cloudflare token Show and a bucket key Show are listed under Account activity. Show still needs the Hub password. Load zones stays a click. The Cloud dashboard no longer lists token zones on a refresh. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.124 =
* New - The Cloud dashboard no longer lists token zones on a refresh. Load zones stays a click, is listed under Account activity, and is refused after eight tries in 15 minutes. A bound zone name on a site card still shows from the saved bind. Listing Cloudflare zones stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.123 =
* New - Listing Cloudflare zones stays a click, is listed under Account activity, and is refused after eight tries in 15 minutes. The Cloudflare CNAME stub stays a click, is listed under Account activity, and is refused after eight tries in 15 minutes. Saving a zone still needs the Hub password. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.122 =
* New - Saving a Cloudflare zone needs the Hub password, and 2FA when enrolled. That write is listed under Account activity and shares the eight-try Cloud firewall burst. Turning Cloud firewall on or off, or disconnecting one site, still needs the Hub password. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.121 =
* New - Turning Cloud firewall on or off, or disconnecting one site, needs the Hub password, and 2FA when enrolled. Those writes are listed under Account activity and refused after eight tries in 15 minutes. Saving a zone stays a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.120 =
* New - Saving or disconnecting a Cloudflare token needs the Hub password, and 2FA when enrolled. Those writes are listed under Account activity. Push, remove, and disconnect one site stay a click. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.119 =
* New - Extra protection Refresh is refused after eight tries in 15 minutes and is listed under Account activity. Saving or removing bucket keys needs the Hub password, and 2FA when enrolled. Extra Show stays passwordless. Care operator reveal stays passwordless. A hash_check or db.sha256 archive that names a Site ID must keep its bind.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.118 =
* New - A hash_check or db.sha256 archive that names a Site ID must keep its bind. Stripping bind then rewriting bytes and listed hashes is refused. A 2.1.117 hash_check bind, a 2.1.116 file-inventory bind, a 2.1.115 file-inventory bind, a 2.1.114 created-time bind, and a 2.1.113 Site ID bind still verify. Print remasks revealed keys. Extra Show stays passwordless. Care operator reveal stays passwordless.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.117 =
* New - New linked backups bind hash_check and db.sha256 so stripping those markers is refused. A 2.1.116 file-inventory bind, a 2.1.115 file-inventory bind, a 2.1.114 created-time bind, and a 2.1.113 Site ID bind still verify. Extra Show stays passwordless. Care operator reveal stays passwordless.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.116 =
* New - Restore refuses extracted files or SQL that do not match a listed sha256. Archives without those hashes still restore. A 2.1.115 file-inventory bind, a 2.1.114 created-time bind, and a 2.1.113 Site ID bind still verify. A Care WordPress access reveal is listed under Account activity. Extra Show stays passwordless. Care operator reveal stays passwordless.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.115 =
* New - An Extra Show is listed under Account activity. New linked backups bind Site ID, created time, and file inventory; a 2.1.114 created-time bind and a 2.1.113 Site ID bind still verify. A Hub that sends X-Bedrock-Package-Sha256-Required, or a Hub this plugin already saw send a zip SHA256, is refused when that header is missing. Hub zip fetch does not follow redirects. Extra Show stays passwordless.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.114 =
* New - Signing out one device needs the Hub password even when 2FA is off. The session list shows signed-in time. Extra Show burst now refuses after six reveals in 15 minutes. Extra Show stays passwordless. New linked backups bind Site ID plus created time; a 2.1.113 Site ID bind still verifies. A Hub-served plugin update is refused when X-Bedrock-Package-Sha256 is present and does not match.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.113 =
* New - Sign out all devices and Sign out other devices need the Hub password even when 2FA is off. A Care operator reveal hides after 15 seconds, remasks when you leave the tab, and is burst limited. Care operator reveal stays passwordless. New linked backups write an HMAC bind; a tampered bind is refused. Offline Pro extras stay only when the last heartbeat was still live. Hub plugin-download sends X-Bedrock-Package-Sha256.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.112 =
* New - A revealed Site key or extra protection key hides after 15 seconds. Extra and bucket keys remask when you leave the tab. Extra Show is IP and burst rate limited and writes a customer activity row. Extra Show stays passwordless. Operator Extra enable and disconnect need the Hub operator password. Offline Pro extras stay only when the last token was active. This plugin only installs from wordpress.org, a local zip, or the connected Hub.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.111 =
* New - Extra protection turn on and turn off need the Hub password, and 2FA when enrolled. Extra Show stays passwordless. Public Care status no longer shows a WordPress username or login URL. Every Hub rate bucket fail-closes when SQLite is busy. New backups write this Site ID; restore refuses a mismatch when both sides are set.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.110 =
* New - A failed Connect rolls back so a wrong Site key cannot leave the site Linked or turn Pro extras off. Disconnect wipes the leftover encrypted Site key. Extra protection disconnect refuses a closed account. Vendor site ids keep only letters, numbers, underscore, and hyphen.
* New - Extra protection on the Hub stays Bedrock Shield language only. The customer Hub, help, and this plugin do not name a third-party monitor or show a seat meter. Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.109 =
* New - Extra protection on the Hub is Bedrock Shield language only. The customer Hub, help, and this plugin do not name a third-party monitor or show a seat meter. If extra protection cannot start on another site, Hub says to contact support. Enable stays opt-in for paid Pro and Shield Care. This plugin does not call a third-party monitor API.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.108 =
* New - Hub vendor-monitor seats. Env-only App API key on the Hub host. Enable is opt-in for paid Pro and Shield Care. We never auto-delete a connected site. The dormant vpatch-feed adapter stays off. This plugin does not call a third-party monitor API.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.107 =
* New - Marketing visual pass. Same Plus Jakarta Sans. Same marketing brand colors. Two-column hero, soft cards, numbered Connect Protect Restore steps, and a taller recommended Pro card. Cited US security stats stay. Basic stays $15 / month. Cleanup stays $99 once. Checkout still collects email.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.106 =
* New - Marketing home and pricing restyle. Same Plus Jakarta Sans. Same marketing brand colors. Cited US security stats stay. Setup is Connect, Protect, Restore. Basic stays $15 / month. Cleanup stays $99 once. Checkout still collects email.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.105 =
* New - Care cleanup access. After a $99 pay, the ticket waits on WordPress login (URL, username, password, or a temp admin invite). Hosting login is optional. Credentials stay sealed. Operators reveal with a passwordless Show. Work cannot start without WordPress access. A closed account cannot submit.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.104 =
* New - Continued deep exploit hunt. Subscriber REST privilege routes stay blocked even when a storefront user is logged in. X-Forwarded-Proto is honored only behind a trusted hop. Plugin download sends Cache-Control private, no-store. Leftover dump files stay off the Hub router.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.103 =
* New - Wordfence-driven attacker-block layer. Pattern guards block header traversal, unauth REST privilege and leak routes, template LFI, unauth admin-ajax POST, dangerous upload content-types, and known webroot backup names. Backup store writes web.config deny. Dashboard flags most-targeted plugin slugs that are present. There is no live CVE feed without an API key.
* New - Site key Show stays passwordless and rate limited (2.1.29 UX). Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Prices stay $15 Basic / $99 cleanup. Not unhackable.

= 2.1.102 =
* New - Continued deep exploit hunt. Composer production stays empty. Watch refuses 0.0.0.0 and mapped loopback. Plugin scan history stays autoload=no. Hub prune keeps twenty live sessions. Reset tokens leave the query string. Connect Hub errors stay escaped. Stripe portal return stays pinned.
* New - Connect refuses a Hub URL with userinfo so wp_remote cannot send HTTP Basic. Care operator list has no OFFSET page. Non-auth rate buckets still fail-open if SQLite is busy. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.101 =
* New - Continued deep exploit hunt. Operator LIKE still escapes stored nicknames. There is no operator sample import leftover. Plugin Location stays wp_safe_redirect. 2FA backup consume stays compare-and-swap with no regenerate wipe leftover. Backup download stays path-only with same-origin Referrer-Policy. Integrity hashes use a literal algorithm, not an option.
* New - CSV export still prefixes classic equals-cmd pipe formulas. mu-plugin drop still checks is_writable. billing_events stay after close so Stripe event ids stay unique. HTTPS redirects still pin to app_url. Dual Transfer-Encoding plus Content-Length is refused. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.100 =
* New - Continued deep exploit hunt. HTTPS redirects pin to app_url when it is set. Dual Transfer-Encoding plus Content-Length is refused. Post-login return stays customer.php. Account upsert writes a known column set. Mail bodies are PHP templates, not SSTI. There is no GraphQL leftover. Outbound TLS verifies but does not pin a certificate.
* New - There is no nopriv AJAX leftover. The plugin does not filter cron_schedules. First activate still snapshots the must-use baseline from disk. Hub SQLite backup still re-restricts WAL sidecars. Operator sessions still call lockdown before start. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.99 =
* New - Continued deep exploit hunt. Hub has no unserialize. Help articles are an in-memory map, not a user-supplied include path. Stripe webhook verifies the signature before decode and enqueue. There is no account merge or transfer leftover. The router refuses phpinfo leftovers. Site IDs retry on UNIQUE collision. Job enqueue stays on an allowlist with a 256 KB JSON cap.
* New - Mutating plugin AJAX stays logged-in admin with no nopriv hook. Restore still trusts a backup this site created. CSRF still requires the session token when Origin and Referer are both missing. Hub SQLite backup still re-restricts WAL sidecars. Operator sessions still call lockdown before start. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.98 =
* New - Continued deep exploit hunt. Hub SQLite backup re-restricts dest and source WAL, shm, and journal sidecars after VACUUM INTO or the copy fallback so a umask 0022 snapshot cannot leave world-readable sidecars. Operator session start calls the same lockdown as a customer session before start so URL session ids and trans_sid stay off.
* New - Rate buckets use server time() and ignore a forged Date header. Ingest nonce uniqueness survives VACUUM INTO because it is a dest snapshot, not a live rebuild. Operator notes stay text with no attachment sink. There is no marketing contact form. Plugin firewall first-hit wins so a later allow cannot bypass a deny. Protected score stays local firewall, lockouts, scan, and clean; handshake features cannot inflate it. Update host pin runs on upgrader_pre_download before the package downloads. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.97 =
* New - Continued deep exploit hunt. Hub 2FA enroll stays compare-and-swap so two overlapping starts cannot mint two enabled secrets. Plugin license ciphertext stays autoload=no. Watch fetches still pin CURLOPT_RESOLVE so DNS cannot rebind after the allowlist. Pack download version is an integer, not a filesystem path. The plugin activity log table escapes every column. Seat add uses Hub subscription quantity plus a 1-to-20 cap, not a client-supplied new total. Operator login stays IP plus user plus 2FA bucketed. Plugin Disconnect stays a local unlink. Care status tokens stay 32-hex with a lookup floor.
* New - Care ticket create still takes the cleanup_create floor. Operator password rotate still uses the 12-to-128 window. Customer TOTP consume already stays compare-and-swap. Hub absolute session lifetime still uses login time, not last-seen. Plugin settings stay off REST. Backup download tokens stay HMAC-SHA256. Plugin scan queue still needs manage_options and a nonce. Checkout success stays on the Hub connect or login path. Login and reset still share generic copy. Unban-my-IP still needs a POST nonce. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.96 =
* New - Continued deep exploit hunt. Care ticket create from the backup page or plugin HMAC takes the same cleanup_create floor as the Care form so a stolen session cannot open more than six tickets in 15 minutes. Operator password rotate uses the same 12-to-128 window as a customer so an overlong string cannot hang Argon2id.
* New - Customer TOTP consume already stays compare-and-swap. Hub absolute session lifetime still uses login time, not last-seen. Plugin settings stay off REST. Backup download tokens stay HMAC-SHA256. Plugin scan queue still needs manage_options and a nonce. Checkout success stays on the Hub connect or login path. Login and reset still share generic copy. Unban-my-IP still needs a POST nonce. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.95 =
* New - Continued deep exploit hunt. Login flood takes the same dummy-hash floor as reset so a guessed password cannot be timed against a lockout. Operator TOTP consume is compare-and-swap so a reused window code cannot grant twice. Setup-mail URLs refuse a plain HTTP origin unless this is a loopback preview.
* New - Quarantine list stays this blog option. There is no operator export of api_key. Stripe event ids are not purged. Firewall blocklist keys the client IP, not Host. Hub jobs do not steal a running row. Connect success stays on wp-admin. Care operator updates after done still write an audit row. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.94 =
* New - Continued deep exploit hunt. Operator restore and Show mint refuse a closed tombstone so Connect cannot look restored while the Site key stays dead. Handshake suspends a closed account even if a registry row was reminted. Mail From strips CR/LF and angle brackets from the display name.
* New - Login still regenerates the session id before auth flags. Watch fingerprints still include account_id. The local backup key is still a random hex option, not a passphrase. There is no IP ban list import. JSON errors still stay slugs. CORS still never echoes Origin. Pack signature checks do not skip when WP_DEBUG is on. Care credit stays a derived count. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.93 =
* New - Continued deep exploit hunt. Account close claims the closed tombstone before Site keys are revoked so a concurrent restore cannot leave a live key on a closed row. Hub SQLite snapshots refuse a symlink dest. Care public status sends Cache-Control private, no-store.
* New - There is still no operator impersonation cookie. Plugin outbound HTTPS still forces TLS verify. X-Forwarded-For stays gated. There is no firewall rule import that parses YAML or PHP objects. Stripe webhook auth stays the HMAC secret. Connect still needs a wp-admin nonce. Paid checkout apply still takes BEGIN IMMEDIATE plus a unique session id. Closed-account Hub jobs still skip. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.92 =
* New - Continued deep exploit hunt. Closed-account Hub jobs are skipped: backup enqueue will not queue them, dispatch acks and skips them, backup_run and Watch deliver refuse them. There is no remember-me cookie. Hub email stays Stripe-only. Connect still refuses metadata IPs. Pack apply still refuses a downgrade. Logger stays table-only. 2FA backup codes are not printed in an HTML comment. Stripe API sends no Idempotency-Key.
* New - Scan pause and resume still need manage_options and a nonce. Setup mail has no continue URL. Billing portal still takes the Stripe lock. SameSite=None without Secure still falls to Strict. Site nicknames still refuse URL, punycode, and C0 controls. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.91 =
* New - Continued deep exploit hunt. Billing portal session create takes the Stripe account lock. SameSite=None cookies without Secure fall back to Strict. Site nicknames refuse URL, punycode, and C0 control characters; unicode labels stay.
* New - Scan finding paths stay escaped. Operator notes stay escaped. A revoked Site key still gets a signed suspend. Care has no file-upload sink. Uninstall still deletes the Site key ciphertext. robots.txt names no sitemap. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.90 =
* New - Continued deep exploit hunt. CSV export treats NBSP, zero-width, and fullwidth formula leads as formulas. Public health drops the PHP version. Quarantine restore refuses wp-config and other protected basenames even when the dest is missing. Plan change takes the Stripe account lock and re-reads seat count.
* New - There is no leftover Hub OAuth state cookie. Plugin backup download does not send Content-Disposition. Watch webhook rotate still does not fetch the destination. Care credit stays a derived count. Site key paste still does not land in debug.log. Mail preview still needs an operator. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.89 =
* New - Continued deep exploit hunt. Stripe webhook signatures refuse an empty body. Hub IP rate buckets fold IPv6 to /64 so a shared prefix cannot spray; tenant extras never fold. Ingest and Stripe webhook keys use that fold. A customer password change still kills sibling Hub sessions. Hub 2FA disable still needs the password.
* New - Site key restore stays compare-and-swap. Care public status stays a 32-hex token. Restore archive members still refuse parent paths. Quarantine delete still needs a POST nonce. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.88 =
* New - Continued deep exploit hunt. Operator password rotate kills other Hub operator sessions. Ingest and handshake timestamps use an exclusive skew window. Nonce replay TTL is longer than twice that window. Mass site delete takes the Stripe account lock. Setup tokens cannot be looked up after a password exists.
* New - Care notes stay escaped text. Billing portal return stays pinned to app_url. SQLite backup filenames still refuse ATTACH. A fresh plugin handshake token with fewer features wins after a plan drop. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.87 =
* New - Continued deep exploit hunt. A Care cleanup token cannot rewrite intake after refunded, or after done outside the 14-day follow-up. Follow-up is notes-only. Closed accounts cannot export. Mutating plugin scan AJAX refuses GET. Backup-code consume drops exactly one hash. Password-reset rate deny takes the same timing pad as a real request.
* New - Changing the Hub password still revokes every Site key. Site IDs stay. Show or operator restore still mints a new secret. Download tokens still HMAC the session user-agent when one is stored. Leftover non-ASCII after an update-host fold is still refused. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.86 =
* New - Continued deep exploit hunt. Changing the Hub password or turning on two-factor revokes every Site key on that account. Site IDs stay. Show or operator restore mints a new secret. Download tokens HMAC the session user-agent when one is stored. Leftover non-ASCII after an update-host fold is refused. Mass-assign strip drops TOTP and reset leftovers.
* New - License upsert still cannot clobber a live handshake. Two Stripe jobs for one account still take a Hub-side lock. Watch webhook rotate stays compare-and-swap. Hub rate buckets still fold IPv6. Hub cookies stay host-only. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.85 =
* New - Continued deep exploit hunt. License upsert cannot clobber a live handshake. Two Stripe jobs for one account take a Hub-side lock. Watch webhook rotate is compare-and-swap. Hub rate buckets fold IPv6 compression and strip zone ids. Hub cookies stay host-only. Cleanup Stripe session ids stay cs_. Plugin update-host checks fold a trailing dot and punycode.
* New - Shared-browser leftover cookies still cannot retarget another account. Restore jobs stay pinned to one Site ID. Download tokens still need the matching session and user-agent. Handshake timestamps still refuse the 2038 overflow. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.84 =
* New - Continued deep exploit hunt. Leftover customer and operator cookies on a shared browser cannot silently retarget another account. A Hub session without a registry id dies after a password change. Restore jobs stay pinned to one Site ID. Download tokens need the matching session and user-agent. Handshake timestamps refuse the 2038 32-bit overflow. Rate windows stay unix/UTC.
* New - The buyer zip still stays free of tests and secrets. Composer require-dev stays pinned. Hub Docker ignore stays broad. Debug leftover pages still need an operator session. Source maps stay off the Hub static serve. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.83 =
* New - Continued deep exploit hunt. The buyer zip stays free of tests, phpunit, .env, .git, hub-access, private keys, and agent-store paths. Composer require-dev stays pinned. Hub Docker ignore stays broad. Sample configs cannot carry live secrets. Debug leftover pages need an operator session. Source maps stay off the Hub static serve.
* New - Ingest JSON stays width-capped. Nested gzip is refused. parse_str cannot bypass max_input_vars. Log lines and Location values cannot carry CR/LF. Job enqueue stays on an allowlist. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.82 =
* New - Continued deep exploit hunt. Ingest JSON stays width-capped. Nested gzip is refused. parse_str cannot bypass max_input_vars. Log lines and Location values cannot carry CR/LF. Job enqueue stays on an allowlist with a payload cap. Hub SQLite backup closes the snapshot handle. Pack JSON stays size-capped. A scan lock older than 15 minutes is stolen.
* New - Hub 2FA enroll is still compare-and-swap. Closed accounts stay closed on upsert. Tenant rate buckets still refuse an empty extra. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.81 =
* New - Continued deep exploit hunt. Hub 2FA enroll is compare-and-swap. Closed accounts stay closed on upsert. A live email cannot move onto another account. Tenant rate buckets refuse an empty extra. Hub SQLite snapshots stay under backups/hub-*.sqlite. Export filenames stay path-only. Care ticket ids stay cln_ plus 12 hex. Stripe does not push Hub email changes. Hub entitlement cannot carry a WordPress role.
* New - Cloudflare zone updates still take a Hub-side lock. Unsubscribe tokens still expire. CSV formula prefixes still survive a BOM or space. Customer JS still copies own keys only. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.80 =
* New - Continued deep exploit hunt. Cloudflare zone updates take a Hub-side lock so GET-then-PUT cannot interleave. Weekly digest unsubscribe tokens expire after seven days. CSV formula prefixes survive a leading space or BOM. Customer JS copies own keys only. Clipboard fallback textareas turn autocomplete off. Print CSS hides revealed Site keys. CSP blocks object and worker sources.
* New - Billing jobs still claim first. Pack apply still re-reads the stored version. First-operator config create stays exclusive. Public health still drops last24 and job counts. Watch fingerprint extras stay on an allowlist. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.79 =
* New - Continued deep exploit hunt. Billing jobs claim before Watch and backup floods. An older signed pack cannot overwrite a newer stored version. First-operator config create is exclusive. Public health drops last24 and job counts. Handshake timestamps refuse leading zeros and overflow digit strings. Watch fingerprint extras stay on an allowlist. S3 object keys cannot carry a versionId. Leftover sitemap and metrics paths stay off the Hub static serve.
* New - Portal cancel still flips Hub licenses when Stripe is already canceled. Empty pack key_id is still unknown. First claim still refuses a short disposable-domain list. A canceled token still cannot keep leftover Pro extras. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.78 =
* New - Continued deep exploit hunt. A Stripe customer-portal cancel that already shows status canceled flips Hub licenses without waiting for subscription.deleted. An empty signed-pack key_id is unknown. First claim refuses a short disposable-domain list. A canceled token cannot keep leftover Pro extras. Restore writes the live backup key back on every fail path.
* New - Leftover composer.lock, phpunit, and vendor paths stay off the Hub static serve. Nginx examples send Referrer-Policy same-origin. Plus-aliases still share one account. Stripe-mapped Price IDs stay a paid total. HMAC refuses none/md5/sha1 prefixes. Leftover bcrypt still refuses a password longer than 72 bytes. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.77 =
* New - Continued deep exploit hunt. First-checkout emails collapse NFKC and plus-aliases so one mailbox cannot claim two seats. Stripe-mapped Price IDs stay a paid total. HMAC signatures refuse none/md5/sha1 prefixes. Leftover bcrypt customer hashes refuse a password longer than 72 bytes.
* New - Watch fetches still pin the resolved IP. Hub to S3 and Stripe still set SSL_VERIFYHOST. Dual HTTP framing is still refused. The Hub router still keeps static files inside the Hub root. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.76 =
* New - Continued deep exploit hunt. Watch and webhook fetches pin the resolved IP. Hub to S3 and Stripe set SSL_VERIFYHOST. Dual Transfer-Encoding and Content-Length is refused. The Hub router decodes encoded dots and keeps static files inside the Hub root.
* New - Operator LIKE search still escapes % and _. Checkout still refuses GET field pollution and JSON bodies. Connect still refuses a conflicting GET/POST token. Customer mutations still refuse a mixed JSON/form Content-Type. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.75 =
* New - Continued deep exploit hunt. Operator LIKE search escapes % and _. Checkout refuses GET field pollution and JSON bodies. Connect refuses a conflicting GET/POST token. Customer mutations refuse a mixed JSON/form Content-Type.
* New - Cron still prefers X-Bedrock-Cron and strips a query key. License ciphertext and the webhook secret stay off autoload. Closing an account still wipes sealed tokens. Stripe test and live cannot mix. Session cookies stay host-only. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.74 =
* New - Continued deep exploit hunt. Cron HTTP prefers X-Bedrock-Cron and strips a query key from REQUEST_URI and Activity. License ciphertext and the alert webhook secret stay off autoload. Uninstall drops those split options. Closing an account wipes sealed S3 and Cloudflare tokens.
* New - Stripe test and live events cannot mix. Session cookies stay host-only. First checkout still claims one email. invoice.paid without a stored paid checkout stays a no-op. Cron secret min 16, throttle prune, and scrubbed exception logs stay. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.73 =
* New - Continued deep exploit hunt. First checkout claims one email. invoice.paid without an account is a no-op unless a paid checkout is already stored. Cron HTTP requires a 16+ character secret. Throttle rows prune. Exception logs drop keys.
* New - Password reset still pads time and strips the query token. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. The reset page keeps no-referrer. Closed accounts stay skipped. Ingest site_url CAS stays. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.72 =
* New - Continued deep exploit hunt. Password reset takes a timing floor and dummy Argon2 so a mailbox cannot prove an email. The reset token is stashed and stripped from the query string. The reset page sends Referrer-Policy no-referrer.
* New - Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Closed accounts stay skipped. Ingest site_url CAS stays. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.71 =
* New - Continued deep exploit hunt. A closed account cannot be revived through the same Stripe customer. Ingest cannot steal a site_url another Site ID already holds. A foreign URL cannot burn another site's ingest cap.
* New - Gzip archive cap, site_url case-fold, Hub router denylist, and 16-byte AES-GCM tags stay. Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.70 =
* New - Continued deep exploit hunt. Gzip backup archives cannot expand past 32 MB or 2000 files. Handshake site_url folds case and drops a trailing-dot host. The Hub router will not serve .env, phpinfo leftovers, or parent traversal.
* New - Watch alert context is clipped so a finding cannot bomb mail or Slack. AES-GCM tags must be 16 bytes or decrypt fails closed. Server-Timing is stripped. Progress counters stay bounded.
* New - Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). IPv4-mapped IPv6 unwrap, password cap, and restore-vs-prune pin stay. Not unhackable.

= 2.1.69 =
* New - Continued deep exploit hunt. Passwords longer than 128 characters cannot hang Argon2id. IPv4-mapped IPv6 cannot SSRF. Handshake and ingest site_url drop userinfo and homoglyph hosts. Restore pins the copy so prune cannot delete it mid-write.
* New - Hub scripts carry sha384 integrity. Slack and webhook sends re-check the public URL. Custom S3 hosts cannot resolve to a blocked IP. SQLite WAL uses a bounded checkpoint. Permissions-Policy locks extra sensors.
* New - Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Must-use helpers wrap functions and realpath so a symlink install cannot redeclare. Not unhackable.

= 2.1.68 =
* New - Continued deep exploit hunt. A revoked Site key can still prove HMAC so the plugin receives a signed suspend, but it cannot ingest, touch last-seen, or take a backup job.
* New - Activity CSV and the JSON pack prefix formula cells. Quarantine claims the inode so a symlink swap cannot move another file. Site IDs retry on a primary-key collision. CORS preflight is denied. Plugin outbound HTTPS always verifies TLS. Re-activating a revoked Site mints a new key. Must-use helpers wrap functions and realpath so a symlink install cannot redeclare.
* New - Hub Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.67 =
* New - Continued deep exploit hunt. Plan change and account close are compare-and-swap so two concurrent posts cannot both charge Stripe or redact the account.
* New - Ingest stores path-only URIs so API keys never land in Activity. Backup store keys stay tenant-prefixed. Restore refuses a size bomb.
* New - Hub 2FA wipes planted session keys after the password step. Stripe rejects a timestamp at the replay edge. Must-use helpers skip a second load so a symlink install cannot fatal the site. Referrer-Policy stays same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.66 =
* New - Continued deep exploit hunt. Hub CSRF also checks Origin or Referer when the browser sends one. Watch alert fixed_in is escaped and update links stay on that site's https wp-admin.
* New - Backup download tokens are one-use. Cleanup status token lookups are rate limited. Job claim is compare-and-swap. Handshake strips billing fields and cannot steal another site_id.
* New - Mesh user-meta never instantiates PHP objects. Entitlement heartbeat is hourly so a plan drop lands soon. Mail buttons reject javascript and data links. Hub Referrer-Policy is same-origin so Chrome form posts keep the session cookie. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.65 =
* New - Continued deep exploit hunt. Password-reset completion is compare-and-swap so two concurrent completions cannot both set a password.
* New - Backup prune re-counts ready offsite copies under a write lock and never deletes the last good offsite copy.
* New - Ask Bedrock drops LLM answers that invent features we do not ship. Operator ingest URLs pin to app_url. Billing event ids are never NULL. Logger scrubs AKIA keys and key_enc. Connect export strips the encrypted Site key. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.64 =
* New - Continued deep exploit hunt. Site key rotate is compare-and-swap so two concurrent rotates cannot both return a live key.
* New - Quarantine restore resolves the dest under ABSPATH and refuses .., encoded dots, and symlink parents outside the install.
* New - 2FA backup codes and TOTP steps are consumed once. A late Stripe invoice.paid cannot reopen a canceled or closed plan. Webhook events without a real event.id are dropped.
* New - Scan progress refuses PHP objects. Local backup keys stay 64-hex. Cloudflare save ignores a posted account_id. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.63 =
* New - Deep exploit hunt. Connect sets a password only once. A leaked checkout session id cannot overwrite a password you already set or reveal keys again.
* New - Paid seats and tier follow Stripe Price IDs. Session or subscription metadata cannot raise Basic to Care or add seats you did not buy.
* New - Checkout success/cancel stay on the configured Hub origin. Stripe Checkout and Billing Portal Location must be stripe.com. Local test checkout stays.
* New - Adversarial suite covers auth, IDOR, CSRF, SSRF, path traversal, backup/restore, plugin AJAX/REST, rate limits, session expiry, and S3/CF Show. Site key Show stays passwordless and rate limited (2.1.29 UX). Not unhackable.

= 2.1.62 =
* New - Hub sessions expire after 30 idle minutes and 12 hours total. Account still lists and revokes sessions. Adding seats or changing plan rotates the session id and CSRF.
* New - Bucket key Show and Cloudflare token Show need the Hub password, and 2FA when enrolled. Site key Show stays passwordless and rate limited (2.1.29 UX).
* New - Buyer backup download also needs the matching Hub session. Advertised Connect URL prefers the configured Hub origin. Operator Slack is SSRF-safe. Plugin drops IP Hub URLs after handshake.
* New - Home band and help: Hub sessions expire. Bucket and Cloudflare Show need a password. A stolen session can still click Site key Show until you sign out other sessions. Not unhackable.

= 2.1.61 =
* New - Continued white-hat pass on the plugin, Hub dashboard, and customer API. Show on bucket keys and Cloudflare tokens is rate limited and fail-closed. Watch raises s3_abuse and cf_abuse (quiet hours do not mute).
* New - force_https redirects pin to app_url. Activity drops query strings and ignores spoofed account_id or offset. Help HTML is allowlisted. Customer sessions set strict mode. Hub never echoes Origin.
* New - Plugin admin-post returns stay on wp-admin. Settings stay off REST and cannot overwrite Connect secrets. Scan findings stay escaped. Quarantine and backup paths still reject ..
* New - Home band and help article "What we keep locking down." A stolen Hub session can still click Show until you sign out other sessions. Not unhackable.

= 2.1.60 =
* New - Own API and Site key hardening. Unknown, wrong, and revoked keys all return unauthorized. Production ingest and pack pulls require a Site ID so the shared ingest secret is not enough. Registry lists keep only the last four of a key.
* New - Rotate and disconnect need the Hub password (and 2FA when enrolled). Both sign out other Hub sessions. Watch raises key_abuse and key_stuffing (quiet hours do not mute) plus key_rotated and key_disconnected.
* New - White-hat pass on plugin, Hub dashboard, and customer API: quarantine restore re-checks ABSPATH, Protect cannot post lockdown, login JSON drops account_id, Hub JSON is no-store, public http Hub URLs are rejected when force_https is on.
* New - Dashboard card "Your Site key" with Protected / At risk / Unknown. Care: if the Hub login may be stolen, sign out other sessions, change the password, and rotate every Site key. Keys are as safe as the Hub login plus the Show click. Not unhackable.

= 2.1.59 =
* New - Supply chain and trusted-script defense. Scanner and Watch look for poisoned update hosts, remote unserialize gadgets, Ethereum RPC C2 strings, fake WooCommerce companion plugins, Adminer and Tiny File Manager, wp-config.php append after wp-settings.php, leftover 2FA and mail-queue tables, and filters that force auto-updates off.
* New - Stop skilled attacks also blocks a sudden package-host change (wordpress.org and the last-known vendor host stay allowed), quarantines fake Woo companions, and requires a recent Users-screen visit before REST can create a user. Zip-install lock from 2.1.56 stays.
* New - Watch events: poisoned_update_host, remote_unserialize, ethereum_c2, fake_woo_companion, wpconfig_append, and totp_mail_exfil (quiet hours do not mute) plus auto_update_killed (can mute). Cloudflare Connect blocks Adminer / Tiny File Manager paths and challenges public ETH RPC strings.
* New - Dashboard card "Supply chain and trusted scripts" with On / Needs Cloudflare / At risk, Care copy, and one-click skilled mode. Home marketing band cites State of WordPress 2026, WP Beacon, Sansec, and the 2026 Pro update-channel cases. Cannot vouch for every wordpress.org author. Cannot rewrite every CDN script. Not bulletproof.

= 2.1.58 =
* New - Always keep 1 encrypted offsite copy. Hub and plugin show Protected / At risk / Unknown. Protected only when a checked locked copy sits in an S3-compatible bucket off this host inside the keep window. Local and same-server copies never count.
* New - Short Hub Backups setup for Amazon S3, Cloudflare R2, or Backblaze keys. Keys are locked and click-to-reveal. Server environment keys still work and win if set. Bring your own bucket this round.
* New - We never delete the last good offsite copy when a new copy fails. Watch events: offsite_copy_missing and offsite_copy_stale. If this computer looks dirty, restore the Hub offsite copy taken before the hack.
* New - Home marketing band "Always keep 1 safe copy off your host." Needs a bucket and keys. An attacker who also has those keys is out of scope. First Protected needs a successful run. This is not a substitute for host patching.

= 2.1.57 =
* New - Post-foothold reinfection and credential-theft defense. Scanner and Watch look for plaintext password dumps, passwordless auto-login helper files and query params, admin Service Worker registration, sibling path walks, fake file-manager AJAX with no plugin, notification-kill filters, and the Apex Logger 93819 mtime tell.
* New - Stop skilled attacks also interrupts passwordless auth-cookie minting when WordPress hooks still run, strips Service Worker registration on wp-login and wp-admin (known PWA plugins stay allowlisted), and can quarantine reachable helper PHP under wp-content. Zip-install lock from 2.1.56 stays.
* New - Watch events: credential_harvest, auto_login_trapdoor, and fake_file_manager (quiet hours do not mute) plus admin_service_worker and lateral_spread_hint (can mute). Cloudflare Connect blocks helper PHP paths and trapdoor query params. Free-plan custom rules still push.
* New - Dashboard card "Reinfection and credential theft" with On / Needs Cloudflare / At risk, Care copy for browser SW cleanup, sibling sites, and key rotation. Home marketing band cites public SC 4.0.3 / Apex Logger / Monarx / Sucuri reporting. Bedrock cannot wipe another browser. It is not bulletproof.

= 2.1.56 =
* New - Self-healing mesh defense. Scanner and Watch look for auto_prepend in .user.ini, hostile drop-ins, hidden PHP loaders, hex ZIP restore bundles, theme functions.php fence injections, dual must-use and plugin copies, mesh options/cron, and hidden admins. Host crontab and shmop stay outside plugin reach.
* New - Stop skilled attacks also locks the theme editor (DISALLOW_FILE_EDIT, already on in Stop AI attacks), blocks plugin and theme zip uploads from the dashboard, and can quarantine a new unexpected drop-in. This is not DISALLOW_FILE_MODS. Updates still go through Plugins, Hub, or the host.
* New - Watch events: self_healing_mesh and hidden_admin (quiet hours do not mute) plus mesh_stealth (can mute). Cloudflare Connect blocks HTTP probes for .user.ini, php.ini, wp-content/db.php, and sunrise.php. Free-plan custom rules still push.
* New - Dashboard card "Self-healing mesh defense" with On / Needs Cloudflare / At risk, Care cleanup order, and one-click skilled mode. Home marketing band cites Sucuri, The Hacker News, and Monarx (October 2026 SC mesh). Bedrock does not patch PHP or core. This is not bulletproof.

= 2.1.55 =
* New - Skilled attacker defense (Stop skilled attacks). Early must-use gate blocks unauthenticated REST batch/v1 abuse with triple-slash desync or nested users/posts chains (CVE-2026-63030 class). Woo and Stripe webhooks stay allowed.
* New - Instant Watch alerts for unexpected admins, admin bursts, app passwords, and plugin installs after a batch burst. Skilled mode can downgrade an unexpected admin to subscriber and sign sessions out. Bedrock does not silently delete users.
* New - Persistence hunt: hidden must-use plugins, site-health option mimics, wp-config loader signals, planted plugin folders, disguised PHP in uploads, WordPress cron reinfectors, unexpected app passwords. Host crontab is outside plugin reach.
* New - Administrator session IP bind (on in severe and skilled). Cloudflare Connect rules for batch triple-slash (block) and anonymous batch (challenge). Free-plan custom rules still push. Login rate limit at Cloudflare still needs a paid plan.
* New - Dashboard card "Skilled attacker defense" with On / Needs Cloudflare / At risk, core-range warning for WordPress 6.9.0-6.9.4 and 7.0.0-7.0.1, and one-click skilled mode. Home marketing band. Bedrock does not patch PHP or core. This is not bulletproof.

= 2.1.54 =
* New - AI attack defense (Stop AI attacks). Dual-bucket login limits send a generic 429 on wp-login POST, XML-RPC auth, and REST JWT / app-password paths. An early must-use plugin drops empty user-agents, sequential probes, and path storms before WordPress finishes booting.
* New - Training scrapers (GPTBot, ClaudeBot, Bytespider, Amazonbot, PerplexityBot) are blocked by default. Search bots stay allowed. Claimed user-agents never skip rate limits.
* New - Login honeypot and timing soft signals. Cloudflare Connect rule pack for AI bots, REST /wp-json/wp/v2/users, and login/xmlrpc challenges. Login rate limit at Cloudflare still needs a paid plan.
* New - Scanner signatures for AI-campaign webshells and integrity watch on the AI defense must-use file. Watch events: ai_attack_wave (can mute) and takeover_signal (quiet hours do not mute).
* New - Dashboard card "Stop AI attacks" with On / Needs Cloudflare / At risk and one-click severe mode. Home marketing band. Bedrock does not patch PHP. This is not bulletproof.

= 2.1.53 =
* New - Extra launch tests: fresh zip install plus Connect Linked, PHP status Check again, scan, Unban, backup Copy now / restore, Watch php_at_risk, Cloudflare skip plus PHP2Shell rules, and local 4242 Checkout.
* New - Black October campaign (home section and black-october.php): "Is your PHP fixed yet?" Honest note that most sites still need the host update. Cites CISA (updated 2026-10-23) and PHP.net archive 2026-10-21. CTAs are Basic $15 / month and cleanup $99. Bedrock does not patch PHP.
* Fix - The scanner no longer flags Bedrock's own intact PHP2Shell follow-up mu-plugin as a planted backdoor or malware signature. A file with that name that does not match the shipped hash is still reported.

= 2.1.52 =
* New - PHP2Shell patch check now verifies the running PHP worker, not only the version number. Hub and plugin show Patched, At risk, or Unknown. If the host installed a fix but PHP did not restart, the status says so. Check again re-reads the worker.
* New - While you wait, Bedrock can turn session.upload_progress.enabled Off in a mu-plugin or .user.ini when the host allows it. That does not fully fix the bug. Only a patched PHP plus a worker restart does.
* New - Watch php_at_risk alerts name CVE-2026-109618 and CVE-2026-109619 and the minimum official fix for that branch. Quiet hours do not mute this class.
* New - Dashboard banner for at-risk PHP, extra scan hygiene (PHP in uploads, new admins, wp-config change), Cloudflare query/path rules, and cleanup tickets that name PHP2Shell. Marketing cites CISA and PHP.net. Bedrock does not patch PHP.

= 2.1.51 =
* Fix - Uninstall now removes backup copies, the backup key, the first-run flag, and the backup cron. The locked backup folder is deleted with the plugin.
* Tweak - Launch-readiness browser pass covers marketing pages, local test Checkout (4242 and a declined card), Hub login, and plugin screens. Locked prices stay $15/$119, $49/$399, $99/$799, $199/$1,490, and $99 cleanup.

= 2.1.50 =
* Fix - No copies yet is a first-run note. The first automatic copy starts in a few minutes, or click Copy now. The page shows how many copies we keep and the size of each copy.
* Fix - Progress uses plain time words (minutes used and time left). After Copy now the list refreshes. A failed restore names the safety copy so you can undo.
* Fix - SQLite restore counts skipped create lines instead of saying zero database changes. Hub Restore says Connect this site first when the plugin has not checked in.

= 2.1.49 =
* New - Backups copy the whole database (every table, in chunks) plus wp-content and your site settings file. Big photo files are included. After the first copy, only files that changed are sent.
* New - You can download your locked copy with a link that stops working in 15 minutes. Restore from the Hub puts the copy back on the linked site. A safety copy is saved on the site first.
* New - Offsite storage can use S3-compatible buckets (AWS SigV4). Keys come from the server environment. Tests still use a local mock. No real cloud keys ship in the zip.

= 2.1.48 =
* New - One-click encrypted backups of files and the database. Pro and Shield Care copy every day. Basic copies once a week. A site not linked to the Hub copies every day on this computer.
* New - Restore first shows what would change. A safety copy is saved before anything is overwritten. Progress shows the bar, the file, time used, and time left in plain words.
* New - Ask for a $99 cleanup from Scanner or the Hub Backups tab. Scan notes (file names and types) go with the ticket. A person replies in 1 business day. This does not clean the site by itself. Shield Care uses the included credit when one remains. A before and after report is stored on the ticket.

= 2.1.47 =
* Fix - PHP2Shell warning is a short in-page note on Bedrock screens only. WordPress no longer moves it into the Hub banner. Posts and Elementor stay quiet. Coverage and Site Health still have the long host steps.
* Fix - Hub Cloud starts with You can skip this. Token steps show after I already use Cloudflare.
* Fix - Watch Check now refreshes the https lock and DNS on later clicks too, then waits a minute.
* New - Hub checks Cloudflare rules once a day in the job queue. Drift never overwrites until you click Re-sync.

= 2.1.46 =
* New - PHP2Shell checks (CVE-2026-109618, CVE-2026-109619). The plugin compares this site's PHP to a Hub-updatable fix table, shows a persistent admin notice and a Site Health test, and reports the result on handshake.
* New - Follow-up block in a must-use plugin: scanner user-agents, php://filter in the query, a known multipart boundary, filename p2s.txt, and PHP_SESSION_UPLOAD_PROGRESS. This stops later attack steps. It cannot stop the first PHP bug.
* New - Scanner looks for PHP in sess_* files, PWNED:: markers, and unexpected PHP in the session save path. Hub Cloud can push the same header and query patterns, plus short-lived scanner IPs.
* Tweak - PHP 7.4, 8.0, and 8.1 stay supported by the plugin and are labeled unsupported, at risk. Copy says your host may have already patched an older version number.
* Tweak - Hub Docker pins php:8.3-fpm-bookworm by digest, turns session.upload_progress off, and uses php_admin_value limits.

= 2.1.45 =
* Fix - Cloud token paste names a Global API Key, a web address, or a token that cannot edit WAF. Bad pastes are not stored.
* Fix - Free Cloudflare plans still get custom WAF rules. The login rate-limit phase is skipped with a plain note. The WordPress plugin still rate-limits wp-login.
* Fix - If you edit Bedrock Shield rules in Cloudflare, Hub shows Rules changed in Cloudflare and a Re-sync button. Disconnect keeps the bind when leftover rules remain.
* Fix - Check now also scans public pages. IPv6 DNSBL uses nibble reverse. The known-bad host list grew by a few kit domains.

= 2.1.44 =
* New - Hub Cloud firewall for sites already on Cloudflare. Paste a scoped Zone read + Zone WAF edit token. Pick a zone. We push login rate limits, an xmlrpc block, known leftover paths from the rule pack, and a bad-bot block. No nameserver change.
* New - Cloud status says Cloud firewall on. Remove rules or disconnect without leaving leftover Bedrock Shield rules. A rule-pack publish syncs connected zones.
* Tweak - Cloudflare for SaaS CNAME onboarding is a stub behind a feature flag. It is not live.

= 2.1.43 =
* Fix - A new valid https lock is a normal renewal, not an alarm. An empty DNS lookup no longer wipes the snapshot.
* Fix - Public-page scan no longer flags normal analytics, CDNs, or page builders. Hidden cookie links and cached HTML are not cloaking.
* Tweak - Watch first-run says waiting and has Check now. Alert setup shows the webhook secret once, uses UTC quiet-hour presets, and hides SMS until the Hub has provider keys.

= 2.1.42 =
* New - The Hub Watch tab pings the public site, checks the https lock and DNS, looks at public blocklists, and fetches a few public pages even if the plugin is off.
* New - Instant alerts can go to email, Slack, a signed webhook, or SMS. SMS stays off until the operator adds provider keys. Quiet hours are optional. The weekly email stays.
* Tweak - Basic Watch is daily for SSL, DNS, blocklist, and the public-page scan, with pings about every 15 minutes. Pro and Shield Care ping about every 5 minutes.

= 2.1.41 =
* Fix - Browsers that request /favicon.ico or /apple-touch-icon.png now receive the Hub mark instead of a 404 and a console error.
* Fix - Turning on Hub two-factor signs out other devices. Only the session that finished enrollment stays signed in.
* Tweak - Release checks cover PHP 8.3 lint, a 2.1.36 zip-replace upgrade, and a live Hub click-through of every buyer path.

= 2.1.40 =
* Fix - A cheaper second checkout with the same email adds seats billed at that plan. Existing higher-plan seats stay put. Account lists each site's plan. Replay and an addon Stripe subscription update do not rewrite or shrink seats.

= 2.1.39 =
* Fix - A second paid checkout with the same email adds sites or upgrades the plan. Replay does not create a second license. Cleanup stays a one-time $99 fee next to a live plan.
* Tweak - Scanner, Vulnerabilities, and empty-result lines use an in-page note so WordPress cannot nest them under the Hub banner.
* Tweak - Pricing, FAQ, and help tell returning buyers to pay with the same email. The success page keeps the add or upgrade note on refresh.

= 2.1.38 =
* Fix - Scanner and Vulnerabilities notices no longer repeat Scan complete. The notice is the result line only.
* Fix - Logs and Audit rewrite leftover n/a plugin names and redact leftover _wpnonce in Detail text, not only new rows.

= 2.1.37 =
* Fix - Plugin zip upload/replace audit rows name the plugin from the upgrader header, destination_name, or plugin_info. A double upgrader_process_complete fire is stored once. Rows no longer say n/a.
* Fix - The finished Scanner card says Scan complete once. The result line is the count or No malware found.
* Fix - Logs Detail and stored request URLs redact _wpnonce, password, key, and token-like query params.

= 2.1.36 =
* Fix - A logged-in administrator is never IP-banned. The request is still blocked. The first anonymous strike is a grace; repeats still escalate. Logs and Dashboard have Unban my IP and Clear all local bans.
* Fix - Log tables fill the wrap and scroll horizontally on a 1024px screen so the Detail column is not cut off.
* Fix - Plugin install audit rows capture the plugin name and version from the upgrader. Site-change login rows fill the User cell from the signed-in account.
* Fix - Dashboard and Coverage show Hub not answering when the Hub is linked but silent, with Update Hub address. They no longer say Protected 4/4 and linked to a Hub plan at the same time.
* Fix - Vulnerabilities never shows an all-clear on an empty dataset. It says Vulnerability list not downloaded yet and how to fix it.
* Tweak - Coverage, Vulnerabilities, Login Attempts, and Audit are on the Bedrock Shield submenu.
* Tweak - Repeated You never change DNS lines and the per-row Open Bedrock Shield, then Logs line are trimmed.
* Fix - License sync is rate-limited on failed Hub check-ins. Duplicate license sync failed log rows are not written on every admin page load.

= 2.1.35 =
* Fix - Scanner no longer pauses at 0 files a few seconds after Scan now. Status polls are read-only. A missing heartbeat on a just-started listing job is not treated as stale. The browser retries through slow listing and transient errors, and only shows an error after a sustained failure.
* Fix - Scan progress uses one leave-and-resume sentence. The red panel no longer says the scan paused and also that it keeps going.
* Fix - File counts show as soon as they are known. ETA is computed from progress instead of staying on Estimating after the total is known.
* Fix - Connect badge says Linked, Hub unreachable when the stored Hub URL cannot be reached. The status box offers Update Hub address. A signed handshake can refresh the Hub URL so a tunnel restart does not leave the site on a dead address.

= 2.1.34 =
* Tweak - Scan findings explain what to do next by type. A host-changed core file says ignore it unless you edited it. Malware still points at Quarantine first.
* Tweak - Connect and Sync now show an in-page wait panel with elapsed time and "Usually a few seconds" instead of a blank screen.
* Tweak - Alert emails open with a plain lede and What to do next, then the technical details. Logs use plain type labels.
* Tweak - The first-run Connect step is labeled optional unless you bought a plan. Hub customer tables at 390px no longer force a 480px minimum width.
* Fix - Scan status polls no longer return tick debug, skipped paths, or the current file. Status polls are capped at one per second per admin.

= 2.1.33 =
* Fix - wp-login.php GET with a same-host redirect_to (including plugin-install.php?tab=upload and reauth=1) is no longer blocked as remote file inclusion. Same-host URLs in params do not trigger RFI or SSRF rules. The block page shows owner recovery on wp-login.php.

= 2.1.32 =
* Tweak - Scanner shows an in-page progress panel the moment you click Scan now, including after a reload mid-scan. The panel has a percent bar, files checked, a plain-words stage, elapsed time, and an estimate only after a real rate is known.
* Tweak - You can leave the page; the scan keeps going. A small Scan running percent chip shows on the Dashboard. Status polls every few seconds; work ticks stay 20 seconds apart for shared hosts.
* Tweak - On finish the panel says Scan complete and results refresh in place. A stall shows a plain error and Try again.

= 2.1.31 =
* Fix - Plugin pages fill the available admin width up to the 1080px cap. Header, Settings, Protection level cards, and the other Bedrock screens no longer stop at a 670px column.
* Fix - Scanner findings and history refresh in place when a scan completes. You do not need to reload.
* Tweak - Older interrupted scans in history read "Stopped, superseded by a later scan" and fold under Older interrupted scans, so a leftover Paused row from before auto-resume is not alarming.

= 2.1.30 =
* Tweak - Hub Show sets an instant Showing state and keeps one reveal in flight. Copy announces Copied to a toast and to screen readers.
* Tweak - Settings Protection level cards use the full 1080px wrap. Click Save settings applies the chosen level.
* Tweak - Connect no longer says Site keys are shown once. Sign in and click Show if the key is masked. The Site ID field uses a bs_ placeholder.
* Tweak - Scanner drops the leftover file-total engineering note. Finding types use plain words, not code font.
* Fix - A Settings POST that omits or forges Protection level keeps the saved level. Unknown values no longer reset Strict or Relaxed to Balanced.

= 2.1.29 =
* Tweak - Hub Connect cards keep Site key masked (last 4 visible). Show reveals it for the signed-in owner without re-entering a password. Copy copies it. Hide remasks. The key auto-hides after 30 seconds or when you leave the page.
* Tweak - Settings still confirm a Protection level save, and plugin screens stay inside a 1080px wrap with a right gutter.

= 2.1.28 =
* Tweak - Settings opens with a Protection level: Balanced (default), Strict, or Relaxed. Each level maps to the existing firewall, lockout, XML-RPC, and rate settings. Individual toggles stay under Customize.
* Tweak - Dashboard and Connect use a cleaner hierarchy. Connect names Shield Care, Pro, and Basic the same way the Hub does.

= 2.1.27 =
* Fix - Default XML-RPC pingback mode now blocks system.multicall. WordPress IXR still served that method after the method-table filter, which a live site showed.

= 2.1.26 =
* Fix - After Connect or Sync now, the Connection status panel matches the Connected badge and shows the Hub plan. A cached token that this request cannot re-verify no longer reads as Not connected / Unknown.
* Fix - Hub URL paste is trimmed. A leftover character after the domain (trycloudflare.comq) asks you to check the Hub URL instead of calling it an invalid public address.
* Tweak - Reloading the Dashboard mid-scan no longer prompts to leave the page. A paused scan resumes on the next Bedrock page load and continues in the background.

= 2.1.25 =
* Fix - Connect accepts https://*.trycloudflare.com Hub URLs (Cloudflare quick-tunnel preview). Private, loopback, and metadata addresses stay rejected.

= 2.1.24 =
* Fix - Hub Protect, Sites, Activity, Alerts, Account, weekly digest, and the first handshake email use the WordPress site title (or the Site label from plugin Settings). The Site ID stays under details.
* Fix - Connect handshake is no longer starved when the same IP has been probing the Hub. A signed Connect for a known Site ID uses the per-site cap. Layout tests bind the nonce to the Connect form.
* Fix - Settings no longer saves hidden Hub URL fields. Packs (virtual patches, blocklist, vulnerability dataset) always come from the Hub you connected, with HTTPS and SSRF checks. Disconnect clears them.
* Tweak - The beginner menu is Dashboard, Scanner, Quarantine, Logs, Settings, Connect. Connect stays visible while the site is unlinked.
* Tweak - After Connect, Hub extras use this site's key. Virtual patches, the blocklist, and the vulnerability dataset schedule within about 15 seconds. You do not paste extra URLs.
* Tweak - PHP 7.4 with WP_DEBUG on is part of the release gate for every plugin screen.
* Tweak - Hub Account and Billing title sites with the WordPress title. Site ID stays under details. Advanced Settings no longer talks about Hub URL fields.

= 2.1.23 =
* Fix - Scanner progress reads skip MySQL SQL_NO_CACHE on SQLite so WP_DEBUG stays clean. Dropping Heartbeat on Bedrock screens also drops wp-auth-check, and Quarantine rows no longer warn when a leftover row is missing time or actor. Last finished findings stay on screen while a new pass runs or a shared-host scan pauses. The in-page progress bar shows again while a scan is live.
* Fix - Settings no longer drop a wp-config forced value when that field is disabled on Save. Locked fields look disabled.
* Fix - Deactivate clears the scan-chunk cron. Delete the plugin also clears scan history and the update/downgrade notices.
* Tweak - Findings show the file path and a Quarantine button. Restore asks for confirm. Auto-quarantine is an Advanced toggle and stays off.
* Tweak - Scan history lists the last finished or paused passes on this site. No Hub required.
* Tweak - Dashboard, Settings, and Connect show a friendly site label (or the WordPress title) instead of leading with a Hub Site ID.
* Tweak - Settings save still confirms in plain words. Send a test alert shows a success note. Hub URL fields sit under a closed details until you connect. Vulnerability Refresh stays hidden until Connect.
* Tweak - Plugin screens reserve height on first paint, keep the 2.1.21 red not-connected banner, and tighten contrast when the OS asks for more contrast.

= 2.1.22 =
* Tweak - First-day Hub mail is shorter: checkout sends the provisioned setup link, the first Stripe receipt waits until a password is set, and the 24h connect reminder only sends if a password was never set. The 72h Protect reminder is no longer auto-queued. Receipts, password reset, and security notices still send.
* Tweak - Hub Protect "Require admin 2FA" asks for confirm in plain words and explains enroll, undo, and the plugin-folder escape. Coverage and the forced-enroll notice document the same path.
* Tweak - A second request firewall is named on Plugins (dismissible) and Coverage, not only the Bedrock dashboard. Caching plugins and page builders are called out as fine.
* Tweak - Scanner Details leads with beginner copy. Request counts, 429s, and tick lines stay under Advanced tick log.
* Fix - HTML weekly digest wraps long lines and URLs on a 390px screen instead of clipping.
* Tweak - Unknown host tools that look like Hostinger, SiteGround, GoDaddy, Bluehost, WP Engine, or similar drop to Review with calm copy when there is no strong webshell signature. A planted backdoor filename still stays critical.

= 2.1.21 =
* Tweak - Bedrock Shield admin screens again show a full-width red "not connected" alert at the top with a large Connect now button. It hides after Connect. The compact notice on the WordPress Dashboard and Plugins screen stays informational.

= 2.1.20 =
* Tweak - An unlinked site no longer shows a red Hub error on the WordPress Dashboard. The notice is informational: Protect is already on, and Connect is only if you just bought a plan.
* Tweak - After a confirmed scan hit, Scanner and the dashboard point at Quarantine first. Quarantine is on the main menu. A paused scan on shared hosting says to leave the tab open and resume.
* Tweak - Coverage explains a brute-force login wait (about 30 minutes) and how to replace a plugin zip in WP-Admin. Disconnect no longer says Protect turns off.
* Tweak - Hub copy matches the plugin: two-factor is optional until you enroll on Profile, any install can quarantine by hand, Pro can auto-quarantine, and help covers zip replace plus login lockout wait.

= 2.1.19 =
* Fix - A scan tick that ends on the time budget, a 429, or a dropped connection no longer marks the in-flight file as "Skipped (could not read)". That leftover is retried. A file is skipped only when shutdown recorded a PHP fatal for that exact path, or the same in-flight file fails twice. A leftover behind the cursor (stale flush of a file already scanned, such as a Carbon locale) is ignored.

= 2.1.18 =
* Tweak - First scans on Hostinger, SiteGround, GoDaddy, Bluehost, and WP Engine stay calm: host-bundled plugins are not treated as "removed from WordPress.org", and host must-use plugins are not called planted malware. WordPress.org lookups use HTTPS with certificate checks and a short timeout.
* Tweak - After install, the dashboard speaks for day 1, day 3, and day 7. Zero attacks is the usual first week. The weekly Hub email stays optional and off.
* Tweak - On a WordPress network, Connect says each site needs its own Hub link. Protect already runs on every site without Connect.
* Tweak - If the Hub is slow or down, the admin handshake waits two seconds and does not retry. Firewall, lockouts, and the scanner stay on. A later Sync now still uses the full signed call.
* Tweak - Replacing a 2.0.x or 2.1.x zip keeps settings and scan history. The update notice says so.

= 2.1.17 =
* Fix - Scanner no longer calls Hostinger AI Assistant vendor libraries malware. char()/fromCharCode needs a long chain plus eval/assert/create_function; move_uploaded_file ignores docblocks and interfaces; locale files such as sc_IT.php are not SC payloads. Composer vendor/ packages from installed.json drop to Review with plain-English probably-safe copy unless a strong signature is present. CRITICAL confirmed stays for real webshells. The last-5-ticks debug log stays under Details.

= 2.1.16 =
* Fix - Scan progress is stored in a tiny custom table via direct SQL (not the options object cache) and the browser sends the last cursor plus job id on every tick. The server uses max(server, client) for that job and never starts a new job when a tick already carries an id. Debug lines show job=, saved=, and readback=. Each allowed request may inspect 5000 files so a ~4300-file site can finish in three ticks.

= 2.1.15 =
* Fix - Scan ticks now persist the content cursor on every exit (including the 8-second time budget) into a tiny sidecar row, and resume from that sidecar plus the last tick log if object cache still serves a SCAN_JOB blob stuck at 0. Current file stays on the job at tick exit. Plugin checksums are fetched once per job and reused; empty results are cached so a 404 cannot become a remote call per file. In-flight DB writes are batched. Each debug line includes list/hash/remote/db milliseconds. Target is hundreds of files per allowed request.

= 2.1.14 =
* Fix - Scan work ticks that find a leftover runner lock now steal it after 30 seconds, or after 8 seconds when the holder is a dead cron. Each ajax reply includes a debug block (action, work vs status, lock holder and age, phase, cursor before/after, files this tick, elapsed ms, exit reason). Details shows the last 5 ticks.

= 2.1.13 =
* Fix - A file that kills a scan request (timeout, PHP fatal, PCRE backtrack, unreadable, or a symlink outside the site) is recorded before it is opened and skipped on the next request. The scanner keeps a cumulative cursor, lists skipped files in results and Details, and still finishes the rest of the tree.

= 2.1.12 =
* Fix - The scanner lists executable-looking files only (PHP, JS, htaccess, and similar), stores that list once, and always shows the cumulative cursor. Each 8-second tick hashes hundreds of files (128 KB read cap, streamed hashes). The browser counts 429s and Failed to fetch itself and polls every 20 seconds so a ~6000-file site can finish in under 5 minutes.

= 2.1.11 =
* Fix - Scan progress reads and writes go straight to the database with autoload off, so LiteSpeed object cache cannot roll the cursor backward. Each allowed ajax request works for up to 8 seconds. The browser waits 10 to 20 seconds between tries and does not depend on WP-Cron. Uploads media, cache, backups, and similar trees are skipped. The scanner page has a Details toggle and no longer links to admin-post.php.

= 2.1.10 =
* Fix - The scanner freezes the file list once per job and keeps one cursor behind an atomic lock, so ajax and WP-Cron cannot race. A click resumes the same job. After a 429 the browser only asks for status (at least 5 seconds, backing off to 60) and cron keeps working. admin-post.php never does scan work. The old 31 vs 36 swing was two walkers counting folders as they went.

= 2.1.9 =
* Fix - Scan now no longer posts file work to admin-post.php (that 504'd on Hostinger). One admin-ajax request does a short batch and returns progress. 429 and 5xx, including Retry-After, mean the host is busy and the scan is still running. A new click clears a stuck lock. WP-Cron / loopback keeps going if ajax is throttled.

= 2.1.8 =
* Fix - Scan now runs in short background batches so a shared-host gateway (Hostinger nginx 504) cannot kill the request. A wait popup shows progress ("Scanning... X of Y files") and a minutes estimate. If a run stops, the next load says "Your last scan did not finish. Try again." and the event is logged. First-run, daily cron, and the database pass use the same chunks. Unlinked sites still scan locally.
* Tweak - Every Bedrock screen shows a full-width red alert when the site is not connected to the Hub, with a Connect now button. A compact dismissible notice can appear on the WordPress Dashboard and Plugins screen.
* Tweak - Plugin screens match the Hub more closely: one dashboard hero with a real 4-check score, KPI tiles, icons on tabs and headings, empty states with a single next step, zebra log tables, Settings toggles with helper text, and clearer buttons on desktop and 390px. Styles stay under .bedrock-shield.

= 2.1.7 =
* Tweak - WordPress admin screens (Dashboard, Scanner, Logs, Settings, Connect, notices, and block pages) use the same Hub design tokens, Plus Jakarta Sans, cards, pills, and toggles. Styles stay scoped and load only on Bedrock screens.

= 2.1.6 =
* Fix - Network Activate seeds every site on the network, and a new site created later gets tables and defaults. WordPress in a /blog folder can activate, scan, open the dashboard, and connect.
* Fix - Connect says this is the next step after you buy a plan. The Hub shows download first, then Hub URL (this Hub, paste as-is).
* Note - 2.1.1 still blocks a plugin zip as embedded PHP. Replace current works from 2.1.2 onward. From 2.1.1, overwrite the folder on disk or delete the plugin first. Settings, logs, and quarantine stay.

= 2.1.5 =
* Fix - An older zip over a newer install keeps settings and shows a plain notice to upload the latest Hub zip. Connect explains WordPress in a folder such as /blog. The dashboard card says Extra attack blocks instead of Virtual patches.

= 2.1.4 =
* Fix - After a 2.1.x zip or plugin update, settings stay and a short notice says so. The dashboard explains the first quiet week (daily scan, optional Hub email). If the Hub is not answering, Connect and the dashboard say this site still protects itself.
* Fix - Two firewalls (Wordfence, Solid Security, All-In-One WP Security) are described as watch mode instead of jargon. PHP below 7.4 still shows a host-switch notice without a fatal.

= 2.1.3 =
* Fix - Hostinger (and similar hosts) changing wp-cron.php is labeled a Host change review note, not a malware finding. Scan complete copy says notes to review when nothing is confirmed.
* Fix - Elementor (and Elementor Pro) REST saves are no longer treated as XSS in POST bodies. Front-end forms still scan. The first idle scan waits for Dashboard, Plugins, or a Bedrock Shield screen so it does not stall the Elementor editor.
* Fix - A clear admin notice if PHP is below 7.4. Coverage states supported PHP is 7.4 through 8.5. Login, xmlrpc, and block pages still send DONOTCACHEPAGE plus LiteSpeed no-cache so WP Super Cache and W3 Total Cache do not store them.

= 2.1.2 =
* Fix - A signed-in user with install_plugins or install_themes (or the matching update/upload caps) and a valid plugin-upload or theme-upload nonce can install a plugin or theme zip from Plugins > Add New > Upload, including replacing Bedrock Shield with a newer zip. PHP inside media uploads, anonymous requests, forged nonces, and roles without those capabilities stay blocked.
* Fix - The database malware scan skips Bedrock Shield options, transients, log tables, and rule packs. Stored scan results that quote signature text no longer trip db_option_malware.
* Fix - Recent critical events on the dashboard hide filescan findings that a later scan no longer reproduces. The same rows stay in Logs.

= 2.1.1 =
* Fix - A signed-in administrator uploading a plugin or theme zip from WP-Admin is no longer blocked by the virtual-patch rule that is meant for unauthenticated install actions. The same POST without a valid login and nonce is still blocked.
* Fix - One virtual-patch match no longer IP-bans a logged-in administrator or locks them out of wp-admin. Banned owners who still have a valid login cookie are unbanned on the next wp-admin request.
* Fix - Block pages say which action was blocked and how to get back in, without rule ids. Recovery: `BEDROCK_SHIELD_DISABLE_FIREWALL` or `BEDROCK_SHIELD_ALLOW_IP` in wp-config.php, or rename the plugin folder.

= 2.1.0 =
* NEW - License client (class-bs-license.php): connects a site to the Bedrock Shield SaaS control plane and enforces the paid tier. A "Connect" admin screen links the site with a Site ID + Site Key from the dashboard; a daily heartbeat refreshes a server-signed entitlement.
* Security - The per-site key is stored ENCRYPTED at rest (AES-256-GCM, keyed from the site's wp-config salts), so a database dump alone cannot reveal it. Requests to the Hub are HMAC-SHA256 signed over method + site + timestamp + single-use nonce + body hash, HTTPS is required with certificate verification on, and every Hub response is signature-verified (hub_response_ok) so a forged or man-in-the-middled entitlement is discarded.
* Security - Entitlements are server-authoritative and tamper-evident: the cached token is signed with the site key and re-verified on every read, so a customer editing wp_options to flip tier basic->pro cannot self-upgrade (the signature fails and Pro stays off).
* Tier gating - Bot protection, geoblocking, virtual patching, the vulnerability scanner, one-click/auto malware removal, and the shared blocklist now check the entitlement. A site that is not linked to a Hub plan (a local or own site) is not gated at all and keeps every feature.
* Fail-safe - If the Hub is unreachable, the last good entitlement keeps protection on for a 72h offline grace. When a subscription lapses (grace_ended / suspended), the firewall KEEPS blocking and the dashboard goes read-only with a reactivation notice - a lapsed bill never leaves a real business exposed.
* Hub - New signed /license endpoint (activate + heartbeat) issuing per-tier/state entitlements, backed by a licenses table that ports directly to Postgres.

= 2.0.2 =
* Full white-hat penetration test of the plugin AND the Hub (two independent adversarial reviews plus a manual Hub review). No unauthenticated-exploitable bug was found; the fixes below close the confirmed integrity/containment/DoS/bypass gaps. See PENTEST-REPORT.md.
* HIGH - 2FA application-password bypass fixed: application passwords authenticate on determine_current_user and skip the 'authenticate' chain (and thus 2FA). Application passwords are now disabled for 2FA-enrolled users, so a stolen app password alone cannot access REST/XML-RPC.
* HIGH - File-scanner directory walk hardened: the entry cap now counts every entry (not only PHP files), symlinked files are skipped, files resolving outside wp-content are skipped, depth is bounded, and one unreadable subdirectory no longer aborts the whole scan. This removes a self-inflicted CPU/IOPS DoS on large or symlink-boobytrapped sites.
* MEDIUM - Hidden login: a logged-out hit on /wp-admin no longer leaks the secret slug via the login redirect (it 404s, exempting admin-ajax/admin-post), and direct POSTs to wp-login.php are now denied too (closing the credential-stuffing bypass).
* MEDIUM - Username enumeration: the core users sitemap and oEmbed author fields are now suppressed for guests (previously bypassed the ?author= / REST users guards).
* MEDIUM - Upload guard: SVG/XHTML are blocked (script-carrying), and the embedded-PHP sniff now covers short tags and <script language="php">, scanning the first 1 MB instead of 8 KB.
* MEDIUM/LOW - SSRF guard: the alert webhook and all Hub sync pulls now refuse private/reserved/link-local/CGNAT/IPv6-internal targets (incl. 169.254.169.254), resolving DNS names and failing closed.
* LOW - 2FA backup-code entropy doubled; TOTP codes can no longer be replayed within their validity window (a used time-step is remembered and rejected).
* LOW - Auth log sanitizes the stored user-agent; uninstall now also clears transients and runs on every site of a multisite network.

= 2.0.1 =
* Security hardening pass on the 2.0 modules after an independent adversarial review (no critical or unauthenticated bug was found; these close integrity/containment/DoS gaps). See SECURITY-SELF-AUDIT.md.
* Virtual patching: rules are now safety-validated (length cap, reject empty-string/over-broad matches, catastrophic-backtracking ReDoS test), and matching runs under a bounded backtrack limit that fails safe - a bad or poisoned rule can no longer 403 the fleet or burn CPU.
* Quarantine: containment now uses a trailing-slash root and fails closed, preventing a sibling-directory (e.g. public_html.bak) bare-prefix escape.
* Adaptive tuning: a learned firewall exemption now applies only to logged-in requests and is matched on (source + field), so it can never become an anonymous firewall bypass.
* Vulnerability + virtual-patch Hub responses are now HMAC-signed and verified on the site before use (integrity no longer rests on TLS alone). Hub deny rules now cover .json and SQLite -journal files, and data/ ships its own deny-all .htaccess.
* Fixed a cosmetic telemetry bug (dataset "last synced" always showed 0).

= 2.0.0 =
* Enterprise expansion. Seven new modules, all designed to add zero per-visit database load on a clean site:
* - Bot Protection: blocks known attack tools / scanners by user agent, and blocks fake search-engine bots (a request claiming to be Googlebot whose IP does not reverse+forward resolve to Google). The DNS verification only runs for bot-claiming requests and is cached.
* - Virtual Patching: blocks exploitation of known-vulnerable code paths before an official fix is installed. Small safe built-in rule set (PHPUnit RCE, Log4Shell/JNDI, .git exposure, known webshell names) plus a signed ruleset pulled from the Hub. Every rule's regex is compile-validated before use, so a malformed or poisoned push is dropped, not honored.
* - Vulnerability Scanner: matches installed plugins/themes/core against a signed vulnerability dataset pulled from the Hub. Matching happens locally, so the site's component list never leaves the server.
* - Geoblocking: block or allow by country via Cloudflare's CF-IPCountry header or an optional MaxMind GeoLite2 database. Fails open when the country is unknown; always lets allowlisted IPs, logged-in users, and verified good bots through.
* - Audit Log: an event-driven record of every change (users, roles, plugins, themes, core, high-value options, file editor, optional posts). Written at INFO severity so it is a record, not an alert.
* - Adaptive ("atomic") Tuning: learns which fields an administrator repeatedly and only ever trips while editing content, and can auto-exempt those exact fields; recommends switching from monitor to blocking once the site has been quiet. Never exempts a field a real anonymous attacker used.
* - Quarantine: reversible removal. A flagged file is moved to a locked, no-exec folder (it stops running) instead of being deleted, and can be restored in one click. Auto-quarantine is off by default.
* Firewall gained a per-field exemption filter (used by Adaptive Tuning) and now records the offending field name.

= 1.6.1 =
* Sentinel SC counter reworked to be READ-ONLY on the hot path: it neutralizes the loader in memory via the option_active_plugins / option_cron filters, so on a clean site it makes zero database writes and adds zero extra queries per request. Database cleanup now happens only on 'shutdown', throttled to once per 5 minutes, and only when SC was actually seen. This removes the write-on-every-request behavior that is unnecessary overhead on shared hosting.
* The generic long "heartbeat" cron pattern is now only stripped when a specific SC sign is corroborated on the same site, so a legitimately long-named cron hook on a clean site is never removed.
* sc-eradicate.sh: fixed a broken nested table-prefix substitution that made the hex-option detection silently do nothing; switched it to `wp option list` + grep (no prefix guessing). Added a per-site wp-cli bootstrap guard so a site where wp-cli cannot boot (e.g. a WP Rocket / advanced-cache drop-in) is flagged for manual review instead of fataling or being reported clean. Bounded the optional --deep grep with -maxdepth. Aligned the cron false-positive exclusions.

= 1.6.0 =
* Hardened against the "SC" malware family specifically (see SC-ERADICATION-RUNBOOK.md), by signature and structure rather than the mutating names:
* - File scanner: SC content signatures (SC_DB_BEGIN, SCV:, the $_scp loader, 0xrpc.io C2, nested gzinflate) and filename patterns (all loader names, .sc_ dirs, .gr_/.g_ daemons, hex loader/payload pairs, payload zips).
* - Database scanner: manifest options (sc_own_manifest/rec/persist), loose hex option names, and the sc_cron_guard / long-random "heartbeat" cron hooks, with the confirmed false-positive exclusions.
* - Sentinel counter-persistence: loads before the malware and, every request, de-registers the loader from active_plugins, deletes the manifest recipe, and removes the SC cron hooks, breaking the regeneration loop from a spot that cannot be disabled from the dashboard.
* - Added sc-eradicate.sh: a dry-run-first, IOPS-safe, signature-based one-pass eradication and hunt script for the whole hosting account.

= 1.5.0 =
* Added the Sentinel must-use plugin (server-hardening/bedrock-shield-sentinel.php): blocks database persistence at the WordPress-API level - rogue administrators, malicious active_plugins registration, poisoned cron, and siteurl/registration hijacks - and cannot be disabled from the dashboard.
* Added DATABASE-HARDENING.md (Sentinel setup, honest raw-SQL limit, and the MySQL privilege approach that actually prevents new tables) and BEDROCK-SHIELD-CAPABILITIES.md (plain-English capabilities summary).

= 1.4.0 =
* Trust hardening so a hijacked admin session cannot undo the protections (see TRUST-HARDENING.md):
* - Config lock via wp-config.php constants (BEDROCK_SHIELD_LOCK_SETTINGS / BEDROCK_SHIELD_CONFIG): forced settings can no longer be changed from the dashboard.
* - Administrator allowlist (BEDROCK_SHIELD_ADMIN_ALLOWLIST or a setting): auto-demotes any admin not on the list, on role change, registration, and every scan - kills the rogue-admin trick.
* - Settings tamper alerts: turning a protection off fires a CRITICAL alert off-site to the Hub.
* - Built-in TOTP two-factor authentication with per-user enrollment, backup codes, and an emergency wp-config bypass.
* - Optional forced auto-updates for core, plugins, and themes.

= 1.3.1 =
* Security self-audit of the plugin's own code (see SECURITY-SELF-AUDIT.md): verified output escaping, prepared queries, capability + nonce checks, direct-access guards, safe redirects, and no ReDoS.
* Hardening: fleet blocklist now requires HTTPS and accepts only public IPs (a poisoned response cannot blocklist internal/CDN infrastructure); login log has a per-IP write cap; the webhook secret is a masked field.

= 1.3.0 =
* Added a database compromise scanner: rogue administrators vs a trusted baseline, malicious code in wp_options, injected posts, malicious/ghost active_plugins entries, malware-named options, and suspicious/orphan wp-cron tasks (the layer Hostinger's file-only scanner misses).
* Added SC-incident detection: known-malware artifacts (warp-router-bit loader, .sc_ hash dirs, core_/own_ hash payloads), drop-in tampering, and .user.ini / .htaccess auto_prepend backdoor loaders.
* Added an hourly reinfection tripwire that alerts the moment a persistence surface (mu-plugins, drop-ins, active plugins, admins) changes - catching self-repairing malware fast.
* Added per-site Hub identity (X-Bedrock-Site) so each site authenticates with its own key and can be revoked individually.
* See INCIDENT-SC-SAFEGUARDS.md for the full incident mapping, eradication checklist, and hosting-isolation guidance.

= 1.2.0 =
* Added adaptive IP bans: repeat offenders earn an escalating hard ban (15m to 7d).
* Added a global per-IP flood cap for application-layer DoS (uses APCu / object cache).
* Added the fleet blocklist: pull attacker IPs seen on your other sites from the Hub and pre-block them here.
* Added full login interception: every attempt across the login form, XML-RPC, REST, and application passwords is recorded to a Login Attempts log.
* Added plugin-security monitoring: weekly alerts on pending plugin updates and plugins removed from the WordPress.org repo, plus an optional file-modifications lockdown (DISALLOW_FILE_MODS).

= 1.1.0 =
* Added arbitrary file-upload prevention (blocks executable types, double-extensions, and files with embedded PHP at upload time).
* Added firewall rule groups for PHP object injection and SSRF (internal / cloud-metadata targets).
* Updated webhook signing to a timestamped, replay-protected HMAC (pairs with Bedrock Shield Hub).
* See VULN-COVERAGE.md for the full mapping of Wordfence vulnerability classes to controls.

= 1.0.0 =
* Initial release.
