=== Brainwerk Security Suite ===
Contributors: brainwerk, stefankogelgruber
Tags: security, brute force, two-factor, malware scanner, firewall
Requires at least: 5.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 0.18.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Privacy-first WordPress security suite — built for EU compliance and Multisite. GDPR-ready by default, transparent about every byte that leaves your server.

== Description ==

Brainwerk Security Suite is a modern, lightweight security plugin built for the European market. It treats privacy as a first-class feature, not an afterthought, and is designed for WordPress Multisite from day one.

= Why another security plugin? =

* **Made in EU / GDPR-First** — IP anonymization is on by default, retention is configurable, the data map is published in the admin so you can paste it straight into your privacy policy.
* **Multisite-aware** — network-wide configuration with clean per-site overrides. (A cross-site *aggregate* dashboard is available in Pro.)
* **A full free feature set** — a real Web Application Firewall, TOTP 2FA, plugin/theme/core vulnerability scanner, file-integrity monitor, malware-pattern scan, and audit log — all free.
* **No Google Fonts, no third-party cookies by default** — the default anti-bot is a 100% local honeypot (no reCAPTCHA). An optional hCaptcha / Cloudflare Turnstile captcha is available if you choose to enable it.
* **Transparent about external calls** — every outbound connection is documented in the **External services** section below. Out of the box the plugin makes **no** automatic outbound calls: the daily vulnerability lookup (EU-hosted, self-hostable) and every other integration are strictly opt-in and off by default.

= Free features — defense in depth =

**Login & accounts**

* Login activity log (success / failure / blocked)
* Brute-force protection: IP-based AND account-based (botnet rotates IPs, account stays locked)
* IP whitelist (single IPs and CIDR)
* TOTP two-factor authentication (RFC 6238) — works with Google Authenticator, Microsoft Authenticator, Authy, 2FAS, FreeOTP, Aegis. 8 single-use recovery codes per user. Force-by-role.
* Magic login links — optional passwordless e-mail login: single-use, 15-minute, rate-limited links, with user-enumeration protection.
* Trusted devices — optional new-device e-mail warning (account-takeover early warning), device fingerprint from UA + IP-subnet + Accept-Language.
* Have I Been Pwned password check — optional, warns on breached passwords via k-anonymity (only a SHA-1 prefix is sent; the password never leaves your server).
* Honeypot anti-bot on login / register / comment forms — 100% local, no reCAPTCHA, no Google data transfer.
* Optional hCaptcha / Cloudflare Turnstile captcha as an alternative to the honeypot (bring your own keys).
* Custom login URL — rewrite wp-login.php to a path of your choice; the original returns 404. Lockout-recovery via wp-config define.

**Firewall & rate limiting**

* **Web Application Firewall (WAF)** — 40+ curated regex signatures for SQLi, XSS, LFI, RCE, SSRF, XXE, command injection, WP user-enumeration and scanner user-agents. Three paranoia levels, admin allowlist, path allowlist, a false-positive viewer with one-click whitelisting, and optional 24h IP auto-block. Off by default — start at level 1.
* Crawler / request rate limiter to blunt aggressive scraping and enumeration bursts.

**File integrity & malware**

* SHA-256 file-integrity monitor over WP core, mu-plugins, plugins, and themes (default: ~10k files indexed). Daily wp-cron sweep detects added / changed / missing files.
* Pattern-based suspicious-code scan (16 rules) on every changed file: `eval(base64_decode(...))`, webshell signatures (c99/r57/WSO/b374k), inline `wp_insert_user(role=admin)`, `preg_replace /e`, remote include via URL — runs only against deltas, not full corpus, so it stays cheap.
* Core-file compare — verify every WordPress core file against the official wordpress.org MD5 manifest to find modified / missing / extra files. Local only, nothing uploaded.
* Repository-integrity check — detection-only comparison of installed plugins/themes against the official wordpress.org packages; reports tampering and links you to the standard reinstall flow (never writes to your plugin/theme files).

**Vulnerability scanner**

* Opt-in daily check (off by default) of every installed plugin / theme / core version against an EU-hosted vulnerability API (default `shieldforge-intel.brainwerk.at`), which aggregates public sources (wpvulnerability.net, EUVD). No API key. The endpoint is configurable — point it at a self-hosted mirror. See **External services** below for exactly what is sent.
* CVE-IDs and CVSS scores with direct links; flagged ACTIVE vs INACTIVE so you know which to update first.

**Hardening**

* One-click toggles: disable XML-RPC (and always strip the brute-force-amplifying `system.multicall`), hide WordPress version, block author enumeration, restrict REST API for anonymous visitors (users / comments / search / settings / themes / plugins endpoints).
* Security HTTP headers — per-header toggle: X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, HSTS, Cross-Origin-Opener-Policy (COOP), Cross-Origin-Resource-Policy (CORP).
* Content-Security-Policy with Report-Only mode for safe rollout — opt-in.
* Disable file editor in admin.

**Detection & response**

* 404 probing tracker (`.env`, `wp-config.bak`, `xmlrpc.php` and friends).
* **Anomaly detection** — explainable Z-score model on login_hour / IP family / user-agent class, per-user adaptive baseline, no cloud calls.
* Live-traffic monitor — optional ring buffer of the last ~1000 "interesting" requests (login, POST, admin, AJAX, XML-RPC) for forensics, auto-cleaned.
* **Incident Commander** — post-incident forensics and one-click lockdown to contain an active compromise.
* **Audit trail** — who changed what when: post edits, user changes, plugin/theme/core updates, security-sensitive option changes (siteurl, admin_email, users_can_register, default_role, network site_admins ...). Useful for incident response and DSGVO Art. 32 compliance.

**Threat Network (opt-in)**

* Optional community threat-intelligence sensor: your site contributes fact-only, hashed attack telemetry and in return receives a signed feed of known-malicious IP indicators. Off by default; raw IPs never leave your server. See **External services** below.

**Admin experience**

* WordPress dashboard widget with **transparent threat score** (0–100), action items, system-status strip, top attackers, recent events.
* Daily digest email with threat score, 24h-vs-7d trend, ASCII heatmap, top targeted usernames, top probing patterns, vulnerable-active-components — pure ASCII so it renders identically through every mail pipeline (php mail / SMTP / OAuth-SMTP / Microsoft Graph).
* **Healthcheck banner** — auto-detects setup issues (proxy IP masking, anonymization off, brute-force disabled) so admins can't ship a broken config.
* Quiet hours that critical alerts can override.

**Privacy & GDPR**

* IP anonymization (default on, /24 for IPv4, /64 for IPv6), username pseudonymization, configurable log retention with daily cleanup, retroactive anonymization helper.
* Privacy dashboard: published data map, one-click DSGVO Art. 15 (access) and Art. 17 (erasure) request workflows.
* Privacy-policy snippet generator (DE / EN).
* Multisite-aware: network-activate, per-site overrides.
* **Onboarding wizard in 6 languages** — DE / EN / FR / IT / PL / ES, language picker as first step.

= Pro features (separate companion plugin) =

Brainwerk Security Suite Pro is an optional paid companion plugin. Details and pricing: https://security-suite.brainwerk.at

* WebAuthn / Passkeys (FIDO2) — phishing-resistant login alongside the free TOTP 2FA
* Geo-blocking with a regularly updated country database (allow/deny on login, register, comment, REST)
* Cloud threat intelligence feed (EU-hosted, opt-in, Ed25519-signed)
* Slack / Discord / Mattermost / Telegram / MS Teams notifications
* Aggregate Multisite dashboard for agencies (cross-site attacker view, per-site scores, network-wide 2FA coverage)
* AI-assisted incident analysis (bring-your-own-key Mistral or self-hosted Ollama)
* Whitelabel mode
* Priority support

== Installation ==

1. Upload the `brainwerk-security-suite` folder to `/wp-content/plugins/` or install via the WordPress plugin uploader.
2. Activate the plugin through the **Plugins** screen (or **Network Activate** for Multisite).
3. Open **Brainwerk Security Suite** in the admin sidebar and walk through the onboarding wizard.

Brainwerk Security Suite ships with safe defaults — no configuration is required to get baseline protection, and out of the box it makes no outbound calls at all. The vulnerability scanner (the one feature that contacts an external API) is off by default; enable it under **Vulnerabilities → Settings** if you want daily CVE lookups.

== Frequently Asked Questions ==

= Does Brainwerk Security Suite call any external service? =

Not until you ask it to. Out of the box the plugin makes **no** automatic outbound calls. Every integration that can reach an external service is opt-in and off by default:

* The plugin/theme/core vulnerability scanner. Once you enable it, it queries an EU-hosted vulnerability API (default `https://shieldforge-intel.brainwerk.at/`) once per day for the slug + version of each installed component. Nothing else (no site URL, no admin email, no IP, no user data) is sent, and you can point it at a self-hosted mirror under **Brainwerk Security Suite → Vulnerabilities → Settings**.
* The Threat Network sensor, the Have-I-Been-Pwned password check, an optional hCaptcha / Cloudflare Turnstile captcha, and the on-demand WordPress.org core-checksum / repository integrity checks.

Each is documented in full in the **External services** section below.

The core local features (WAF, file-integrity monitor, malware-pattern scan, brute-force protection, audit log, 2FA, honeypot, anomaly detection, security headers) make no outbound calls.

= Is the plugin GDPR-compliant out of the box? =

Yes — IP anonymization, configurable retention, and a published data map are on by default. The admin includes copy-paste ready text for your privacy policy.

= Does it work on Multisite? =

Yes. Network-activate it and configure once at the network level; per-site overrides are supported. A cross-site aggregate dashboard is a Pro feature.

= I lost my 2FA device. How do I get back in? =

Use one of the 8 recovery codes generated when you enrolled. If you also lost those, an administrator with `manage_network_options` capability can disable 2FA for any user under **Brainwerk Security Suite → 2FA → Users with 2FA configured → Rescue: disable**.

= I enabled the custom login URL and locked myself out. How do I recover? =

Add this line to `wp-config.php` (above the "That's all" comment):

`define('SHIELDFORGE_LOGIN_RESCUE', 'choose-a-long-random-secret');`

Then visit `https://your-site/wp-login.php?shieldforge_rescue=choose-a-long-random-secret` to bypass the 404 and reach the standard login.

= The WAF blocked one of my own URLs. What do I do? =

Open **Brainwerk Security Suite → Modules → WAF**. The false-positive viewer lists the last 30 blocks; click "Whitelist" next to your legitimate path to add it to the WAF path allowlist. Start at paranoia level 1 and raise it only after watching the block log.

= Will it slow down my site? =

It is designed to be lightweight. Hooks fire only where needed, the database tables are indexed, and old log rows are cleaned up daily. The file-integrity scanner runs at 03:30 in a 45-second time-budgeted cron sweep that resumes on the next tick if a single run can't finish.

= My server runs behind a reverse proxy / Cloudflare Tunnel / sslh. Will Brainwerk Security Suite see real client IPs? =

Brainwerk Security Suite reads `$_SERVER['REMOTE_ADDR']` by default. If your nginx / Apache is configured to forward the original client IP (PROXY-protocol, X-Forwarded-For), that's what arrives in PHP and Brainwerk Security Suite uses it. The healthcheck card on every admin screen will warn you if all visitors arrive as 127.0.0.1 — that means the proxy chain is hiding the real client from PHP, which would silently disable IP-based brute-force protection. Fix it at the proxy / web-server layer (proxy-protocol-aware listener) before re-enabling brute-force protection.

== Privacy Policy ==

= Data stored in your WordPress database (never leaves the server) =

* **Login events**: timestamp, event type (success / failure / blocked / 2FA required / 2FA passed / 2FA failed / logout), username (or hashed pseudonym if pseudonymization is on), IP address (or anonymized /24 if IP anonymization is on — default), user-agent, request URI.
* **Brute-force blocks**: blocked IP, reason, expiry timestamp.
* **WAF blocks**: anonymized IP, request URI, matched rule name, timestamp.
* **Live-traffic buffer** (if enabled): method, anonymized IP, request path, status code for the last ~1000 interesting requests.
* **Anomaly baselines**: per-user statistical aggregates (mean and variance of login_hour, IP family, user-agent class). No raw login history is retained beyond the rolling log retention window (default 30 days).
* **File-integrity baseline**: SHA-256 hash + size + mtime + tracked path of every PHP file under WP core / plugins / mu-plugins / themes. Used to detect added / changed / missing files. The file *contents* are never stored — only the hash.
* **2FA secrets** (per user, if user enrolled): base32-encoded TOTP secret, sha256-hashed recovery codes (the plain codes are shown ONCE on enrollment and never persisted).
* **Trusted devices** (if enabled): hashed device fingerprints per user.
* **Audit trail**: who edited which post / user / option / theme / plugin, with field-level diffs (no post-content bodies, no password hashes — only `[changed]` markers for sensitive fields).
* **Site option**: configuration values, last cron timestamps.

= Data sent to external services =

The plugin makes no automatic outbound calls until you opt in. The one you are most likely to enable is the vulnerability scanner, which — once switched on — queries an EU-hosted vulnerability API (default `https://shieldforge-intel.brainwerk.at/`) once per day. It is off by default; the endpoint is configurable and the feature can be disabled again at any time.

* **What is sent**: per HTTP GET, one slug + one version per installed component (plugin / theme / core). Example: `GET /v1/vulns/plugin/contact-form-7/`.
* **What is NOT sent**: site URL, domain, admin email, IP addresses, user information, content, settings.
* **Provider**: `shieldforge-intel.brainwerk.at` is Brainwerk's own EU-hosted API that aggregates public vulnerability data (wpvulnerability.net, EUVD).
* **Enable / disable**: Brainwerk Security Suite → Vulnerabilities → Settings → Enable scanner (off by default).
* **Self-host**: point the endpoint setting at your own mirror to keep everything in your network.

Several **opt-in** features contact external services only after you enable them — see the **External services** section below for the full list, the exact data sent, and how to turn each off.

= Lifecycle =

All Brainwerk Security Suite data is deleted on plugin uninstall (DB tables dropped, options removed, user-meta wiped, transients purged). The configurable log retention is enforced by a daily cron.

== External services ==

This plugin can connect to the external services listed below. **Every one of them is opt-in and off by default** — out of the box the plugin contacts nothing. Each can be disabled again at any time, and the vulnerability endpoint can be re-pointed at a self-hosted mirror.

**1. Brainwerk Vulnerability API — `https://shieldforge-intel.brainwerk.at/` — OPT-IN, default OFF**

* **What it is used for:** Daily vulnerability lookup for every plugin, theme and WordPress-core version installed on your site. Surfaces known CVEs, CVSS scores and fixed-in versions in the *Vulnerabilities* tab.
* **When data is sent:** Never until you enable the scanner. Once enabled, once per day via WP-Cron (plus any manual "Scan now" you trigger).
* **What data is sent:** One HTTP GET per installed component, with the component slug and version in the path (e.g. `GET /v1/vulns/plugin/contact-form-7/`). No site URL, no domain, no admin email, no IP, no user data, no content, no settings.
* **How to disable:** *Brainwerk Security Suite → Vulnerabilities → Settings → Enable scanner = off*.
* **Self-host / re-point:** set the endpoint option to your own mirror to keep everything inside your network.
* **Provider:** `shieldforge-intel.brainwerk.at` is Brainwerk's own EU-hosted API that aggregates public vulnerability data (wpvulnerability.net — a community mirror of WPScan / Patchstack — and the EU Vulnerability Database, EUVD). Operated by Brainwerk (EU). Privacy: [https://brainwerk.at/privacy](https://brainwerk.at/privacy)

**2. Brainwerk Threat Network (sensor) — `https://shieldforge-intel.brainwerk.at/` — OPT-IN, default OFF**

* **What it is used for:** Optional community threat-intelligence network. Your site shares fact-only attack telemetry and in return receives a signed feed of known-malicious IP indicators.
* **When data is sent:** Only after you give explicit consent AND the site registers with the network. Never before both steps are completed.
* **What data is sent:** Batched, HMAC-signed events containing **hashed, non-reversible IP indicators** (raw IP addresses never leave your server), a hashed user-agent class, a request-path pattern, a country code and — when the User-Agent matches a known crawler (e.g. Googlebot, GPTBot, ClaudeBot) — the crawler's declared family name from a fixed, public allow-list. The raw User-Agent string itself never leaves your server; unrecognised User-Agents send no crawler-family field at all. No site URL owner data, no user identities, no content.
* **How to disable:** *Brainwerk Security Suite → Threat Network → disable* (or simply never enable it). Off by default.
* **Provider:** Brainwerk (EU-hosted), same operator and privacy policy as above.

**3. Have I Been Pwned (Pwned Passwords) — `https://api.pwnedpasswords.com/` — OPT-IN, default OFF**

* **What it is used for:** Warns users whose password appears in known breach corpora, at login or password change.
* **What data is sent:** Only the **first 5 characters of the SHA-1 hash** of the password (k-anonymity range query). The password itself and the full hash never leave your server.
* **How to disable:** Off by default; enable under the login/hardening settings only if you want it.
* **Provider:** Have I Been Pwned, operated by Troy Hunt. [https://haveibeenpwned.com/Privacy](https://haveibeenpwned.com/Privacy)

**4. hCaptcha / Cloudflare Turnstile (optional captcha) — `https://hcaptcha.com/`, `https://challenges.cloudflare.com/` — OPT-IN, default OFF**

* **What it is used for:** Optional captcha on login / registration / comment forms as an alternative to the built-in local honeypot.
* **When it is active:** Only if you enable the captcha module AND enter your own site/secret keys. When enabled it loads the provider's JavaScript from their CDN in the browser and, on verification, sends the captcha token and the visitor's IP address to the provider.
* **How to disable:** Off by default; the default anti-bot (honeypot) is 100% local and contacts nothing.
* **Providers:** [hCaptcha privacy](https://www.hcaptcha.com/privacy) · [Cloudflare Turnstile privacy](https://www.cloudflare.com/privacypolicy/)

**5. WordPress.org (core checksums & repository integrity) — `https://api.wordpress.org/`, `https://downloads.wordpress.org/` — OPT-IN / on demand**

* **What it is used for:** Verifying WordPress core files against official checksums (manual admin action) and, optionally, comparing installed plugins/themes against the official wordpress.org checksums / release packages to detect tampering. The plugin only **reads** these to report differences — it never modifies your plugin or theme files.
* **What data is sent:** The WordPress version + locale, and the slug/version of the components being verified. No user data.
* **When:** The core-checksum check runs only when you click it; the repository integrity check is off by default and, when enabled, runs via cron / on demand.
* **Provider:** WordPress.org (the WordPress project's own infrastructure). [https://wordpress.org/about/privacy/](https://wordpress.org/about/privacy/)

== Screenshots ==

1. Dashboard widget — threat-score header, action items, 24h stat grid with trend arrows, system-status strip, top attackers + targeted users, recent events.
2. Scanner tab — file-integrity baseline status, run-now controls, findings table with re-baseline / whitelist actions, code-snippet preview for malware-pattern hits.
3. Vulnerabilities tab — per-component listing of known CVEs, CVSS scores, fixed-in versions, links to CVE / EUVD advisories, active-vs-inactive flagging.
4. 2FA tab — module enable, force-by-role policy, per-user enrollment status with rescue-disable for lost-device recovery.
5. Audit tab — who-changed-what timeline with per-event-type renderer, filter dropdown, 7-day distribution badges.
6. Modules tab — WAF with paranoia levels + false-positive viewer, security headers, HaveIBeenPwned, trusted devices, live traffic, captcha, magic links, privacy dashboard.
7. Hardening+ tab — custom login URL with live-preview + lockout-recovery hint, honeypot anti-bot toggles, per-header security toggles incl. CSP report-only mode.
8. Anomaly tab — Z-score model, per-user baseline status, recent anomalies with explainable context.
9. Logs tab — searchable activity log with quick block / unblock actions.
10. Privacy / GDPR — anonymization, pseudonymization, retention, data map, Art. 15 / Art. 17 workflows, privacy-policy snippet generator.

== Changelog ==

= 0.18.0 — 2026-08-05 =
* **Threat Network sensor now classifies known crawlers.** When a request's User-Agent matches a known crawler (search engines plus major AI/LLM crawlers such as GPTBot, ClaudeBot, PerplexityBot, Google-Extended), the sensor event sent to the opt-in Threat Network now includes the crawler's declared family name — never the raw User-Agent string, and omitted entirely for unrecognised User-Agents. This is the plugin-side half of the network's bot-reputation feature; verdicts require a minimum number of participating sites network-wide before they appear (k-anonymity floor), independent of any single site's traffic.
* **Security hardening (code-quality gate):** every database query that consumes user input now uses `$wpdb->prepare()` with placeholders; all superglobal reads are unslashed and sanitized; all admin-view output is escaped at output time. Trusted internal table-name interpolation is explicitly documented in-code.
* Added a versioned PHPCS security ruleset (`phpcs.xml.dist`) enforcing `WordPress.Security`, prepared-SQL and direct-query rules — the plugin now passes it with **zero errors**.
* Fixed a TOTP base32 decoding bug that silently discarded lowercase characters from manually-entered authenticator secrets.

= 1.0.0 (geplant) =
* First stable release. Consolidates the full defense-in-depth module set and documents every feature honestly against the shipped code.
* **Web Application Firewall (WAF)** — 40+ regex signatures (SQLi/XSS/LFI/RCE/SSRF/XXE/cmdi/enum), three paranoia levels, admin + path allowlists, false-positive viewer, optional IP auto-block.
* **Crawler / request rate limiter.**
* **Trusted devices** (new-device e-mail warning), **Have I Been Pwned** password check, **magic login links** (passwordless), **live-traffic monitor**, **core-file compare** (wordpress.org MD5), **repository-integrity** detection, **Incident Commander** (post-incident forensics + lockdown).
* **Security headers** extended with Cross-Origin-Opener-Policy (COOP) and Cross-Origin-Resource-Policy (CORP).
* **Privacy dashboard** with published data map and one-click DSGVO Art. 15 / Art. 17 workflows.
* Documentation corrected: the cross-site *aggregate* Multisite dashboard is a Pro feature (the free build provides Multisite support with per-site overrides).
* Domains unified: product/pricing/docs → security-suite.brainwerk.at; company/privacy → brainwerk.at.

= 0.14.4 — 2026-07-29 =
* Maintenance release: version bump only, no functional changes since 0.14.3.

= 0.14.3 — 2026-07-17 =
* **wp.org compliance**: renamed all short-prefixed (`sf_`) transients to the unique `shieldforge_` prefix — `shieldforge_user_lock_`, `shieldforge_2fa_pending_`, `shieldforge_2fa_recovery_show_`, `shieldforge_2fa_attempts_` — to avoid collisions in the shared options/transients space.
* **Metadata**: removed the `Plugin URI` header (the previous value was not public); the public `Author URI` is retained.
* **Hardening**: escape all remaining admin outputs at output time (audit table, scanner status, captcha widget, magic-link/privacy `wp_die` messages) and document the trusted-table-name direct queries.

= 0.14.1 — 2026-07-04 =
* **Privacy**: the plugin/theme/core vulnerability scanner is now **opt-in and off by default** — out of the box the plugin makes no automatic outbound calls at all. Enable it under *Vulnerabilities → Settings* to consent to the daily lookup.
* **wp.org compliance**: all inline `<script>` / `<style>` blocks in admin views are now enqueued (`wp_add_inline_script` / bundled CSS / a static `assets/js/twofactor-profile.js`).
* **wp.org compliance**: the repo-integrity checker is now detection-only — it reports tampered plugin/theme files and links you to the standard WordPress reinstall flow instead of writing files into plugin/theme folders.
* **wp.org compliance**: removed the direct load of `wp-includes/template-loader.php` in the login-URL 404 path; it now emits a self-contained 404.
* **Security**: escape the WAF debug output and the 2FA "last used" column at output time.
* **Docs**: readme reworded to drop comparative marketing claims and to reflect that every external service is opt-in and off by default.

= 0.14.0 — 2026-05-21 =
* **Rebranded** to Brainwerk Security Suite (was: ShieldForge). Display name + text-domain + plugin filename + language files updated. Internal class prefix `Shieldforge_*` and DB tables `wp_shieldforge_*` kept stable for upgrade compatibility.
* **wp.org compliance**: replaced both `<<<TXT` heredocs in the privacy-policy generator with plain string concatenation.
* **Docs**: readme now has a top-level `== External services ==` section documenting every outbound connection.

= 0.9.0 — 2026-05-10 =
* **UX overhaul**: tab navigation grouped into 5 logical sections; hero dashboard with color-coded threat-status banner; modern toggle switches; empty states with CTAs; Quick-Setup wizard (School / Agency / Shop / Blog); mobile-responsive admin; dark-mode support.

= 0.6.0 — 2026-05-10 =
* **Custom login URL**, **honeypot anti-bot**, **Content-Security-Policy** (Report-Only), **per-header security toggles**; new **Hardening+** tab.

= 0.5.0 — 2026-05-10 =
* **User activity audit trail** (11 lifecycle events), new **Audit** tab.

= 0.4.0 — 2026-05-10 =
* **Plugin / theme / core vulnerability scanner** (EU-hosted, no API key), new **Vulnerabilities** tab.

= 0.3.0 — 2026-05-10 =
* **TOTP two-factor authentication** (RFC 6238), recovery codes, force-by-role, new **2FA** tab.

= 0.2.0 — 2026-05-10 =
* **File-integrity monitor** (SHA-256) + **pattern-based malware scanner** (16 rules), new **Scanner** tab.

= 0.1.0 — 2026-05-07 =
* Initial release: login activity log, brute-force protection, IP whitelist with CIDR, hardening toggles, 404 probing tracker, email notifications, daily digest with threat score, anomaly detection (beta), healthcheck banner, onboarding wizard in 6 languages, multisite-aware, GDPR controls, privacy-policy snippet generator.

== Upgrade Notice ==

= 1.0.0 =
First stable release. Documents the full module set (incl. WAF) and corrects the Free/Pro boundary in docs. No breaking changes; internal class/table names unchanged.
