=== SecurityWP ===
Contributors: ini software
Tags: security, hardening, login, headers, privacy
Requires at least: 5.7
Tested up to: 6.5
Requires PHP: 7.4
Stable tag: 1.4.2
License: GPLv2 or later

Lightweight WordPress hardening — login protection, security headers, privacy and head cleanup.

== Description ==

SecurityWP is a focused, no-bloat hardening plugin for WordPress. Every feature
is an independent toggle, grouped into three areas:

**Security**

* Disable XML-RPC, disable the theme/plugin file editor, require login for the
  REST API.
* Limit login attempts (IP lockout), mask the login URL to a secret slug.
* Password-protect the whole front-end.
* Disable comments and pingbacks/trackbacks.
* Prevent user enumeration and information disclosure (directory listing,
  wp-config/.htaccess/backup/log access; Apache .htaccess rules or an Nginx
  snippet).
* Hardening HTTP security headers (X-Frame-Options, X-Content-Type-Options,
  Referrer-Policy, Permissions-Policy).
* ALTCHA proof-of-work login captcha (self-hosted, no third-party calls).
* Traffic monitor.
* Auto-block escalation — a dedicated **IP Block** page that surfaces the
  traffic monitor's suggested blocks for one-click review (Block Suggestion
  System), and an optional **Auto-Block** mode that blocks offending IPs
  automatically on an escalating temporary schedule (1h → 4h → 8h → 5 days →
  2 weeks). Never issues a permanent block automatically; an allowlist and
  verified search-engine bots are always exempt; quiet IPs decay back down.
* Vulnerability scan — a daily check of your installed plugins, themes, and
  WordPress core against the free WPVulnerability database (CC0, no API key).
  Findings appear on a dedicated page and on the dashboard, with an optional
  email alert on new findings. No data about your site is sent — only the
  public slug of each component is looked up.

**Head cleanup**

* Remove the generator/RSD/WLW/shortlink tags, strip asset version query
  strings, drop front-end Dashicons.

**SEO & privacy**

* Disable feeds, disable author archives, obfuscate author slugs, and protect
  email addresses from harvesting.

**INI WP platform**

* Exposes a read-only, HMAC-signed REST endpoint (`secwp/v1/state`) so the
  INI WP control panel can pull this site's security posture and scan results.
  The endpoint only activates when the INI WP connector is installed and
  configured; auth reuses the connector's signed channel.

== Installation ==

1. Activate **SecurityWP** from Plugins.
2. Open **SecurityWP** and enable the hardening you want. Each toggle is
   independent and reversible.
3. For "Mask login URL", set a slug before enabling so you can't lock yourself
   out.

== Notes ==

* Head cleanup lives here, not in SeoWP — SeoWP keeps pure SEO concerns
  (titles, meta, schema, noindex directives).

== Changelog ==

= 1.4.2 =
* Fix: the vulnerability alert's **"Dismiss until something changes"** button now keeps its promise — the alert stays hidden across the daily re-scans as long as they keep finding the **same** vulnerabilities, and reappears only when the finding set actually changes (a new vuln appears, or a fixed one drops off). In 1.4.1 the dismissal was keyed to the scan timestamp as well as the findings, so every daily re-scan brought the banner back even though nothing had changed.
* Compatibility: sites upgrading from 1.4.1 keep their existing dismissal — the old timestamped token is recognized, so the banner doesn't pop back once after the update.

= 1.4.1 =
* Fix: the vulnerability-scan dashboard alert's **Dismiss** button now actually dismisses. The button is a nonce'd link, but the handler only read the action from POST data, so the click was ignored and the banner reappeared — it now reads the request regardless of method.
* Change: **"Dismiss until something changes"** now hides the vulnerability alert until the **next scan runs** (or the finding set changes), instead of staying hidden across re-scans as long as the same vulnerabilities were found. Dismissal is keyed to the scan timestamp + finding-set digest.
* Hardening: **Disable XML-RPC** now also hard-blocks a direct hit on xmlrpc.php with an early 403, before WordPress finishes loading — so bogus XML-RPC floods are cheap to absorb and scanners get a clean 403, not a 200/405. The existing method-neutralizing filters (pingback.ping, system.multicall, etc.) stay in place as defense-in-depth. No server config required; fully portable.

= 1.4.0 =
* New: a dedicated **SecurityWP → IP Block** page — one home for blocking, separate from the Traffic monitor (which stays a read-only forensics view). It shows the system's suggested blocks alongside the IPs you've already blocked, with the manual add-IP box. The blocklist and add-IP box have moved here from the Traffic page.
* New: **Suggested by the system** — the traffic monitor's abuse-threshold candidates (the same ones the INI WP panel already saw) are now shown in the admin with a one-click **Apply block**. Previously these were computed but never surfaced in the UI.
* New: **Auto-block escalation** (Security toggle). Every 5 minutes the engine scores offending IPs and escalates **temporary** blocks on a ladder — 1 hour → 4 hours → 8 hours → 5 days → 2 weeks. By default it only **suggests** (Block Suggestion System); turn on **Enforce** for fully automatic **Auto-Block** mode.
* New: temporary, expiring blocks. Blocks now carry an expiry and a source (manual / suggested / auto); manual blocks stay permanent, while suggested-Apply and auto blocks ride the escalation ladder and expire on their own. Clicking **Apply** on a suggestion now creates a temporary, escalating block (not a permanent one).
* Safety: an IP/CIDR **allowlist** (IPv4 + IPv6) is never auto-blocked, and verified Googlebot/Bing/etc. (reverse + forward DNS) are always exempt — so the engine can't deindex your site or block your own ranges. It **never** issues a permanent block automatically, and an IP with no fresh offense for 30 days **decays** one level.
* New: the platform state endpoint (secwp/v1/state) exposes a read-only `autoblock` block (mode + escalation entries) and emits `autoblock_temp` events for the INI WP control panel. Additive (schema_version unchanged); no connector/signing change.

= 1.3.0 =
* New: **Vulnerability scan** (Security). Once a day SecurityWP checks every installed plugin, theme, and your WordPress core version against the free WPVulnerability database (CC0, no API key) and flags any component whose installed version is affected by a known vulnerability.
* New: a dedicated **SecurityWP → Vulnerabilities** page lists each finding — component, type, installed version, severity, CVE reference, the version it's fixed in, and whether an update is already available — sorted worst-first, with a "Scan now" button.
* New: a **dashboard alert** + a count bubble on the menu when vulnerabilities are found. Dismiss it and it stays gone until the set of findings actually changes (a new vulnerability brings it back).
* New: **opt-in email alert** on new findings only (never on every scan), with a configurable minimum severity and recipient.
* New: the platform state endpoint (secwp/v1/state) exposes a read-only `vulnerabilities` block (counts + findings) for the INI WP control panel. Additive (schema_version unchanged).
* Privacy: no data about your site is sent — only the public slug of each component is looked up; lookups are cached and the daily scan is gated by the toggle.

= 1.2.0 =
* New: **per-IP activity drill-down** in SecurityWP → Traffic. Click any IP in "Top offender IPs" to see a full profile — a clean/watch/suspicious/hostile verdict with the signals behind it, status-code and reason breakdowns, top paths, user agents, and a request timeline — then Block or Unblock right from that page.
* New: a **verdict badge** on every IP in the Top-offenders list (clean / watch / suspicious / hostile), so risky IPs stand out at a glance. An expandable legend next to the day filters explains each level.
* New: the platform state endpoint (secwp/v1/state) exposes the same drill-down for the INI WP control panel — each top IP carries its verdict, and an optional ?detail_ip= returns the full per-IP profile. Additive (schema_version unchanged).

= 1.1.0 =
* New: settings toggles now save via AJAX — flipping a switch no longer reloads the page.
* New: toast notifications confirm every change (enabled / disabled / saved) and surface errors, replacing the old reload-and-show-notice flow. No-JS browsers keep the classic notice.
* New: **Mask version on static assets** (Head cleanup) — replaces the real `?ver=` on CSS/JS with an opaque, salted token. Hides the WordPress/plugin version while keeping cache-busting (the token still changes when the real version does), so it's safer than fully removing `?ver=`.
* New: **Disable oEmbed & REST discovery** (Head cleanup) — removes the REST API and oEmbed auto-discovery `<link>` tags, the `wp-json` HTTP Link header, and the version leak in oEmbed/feed output. The REST API itself keeps working; no endpoint is disabled.

= 1.0.4 =
* Maintenance: no functional changes. Refreshes the self-hosted update manifest so the "View details" → Changelog window renders the full, formatted version history (matching SeoWP). Safe to install.

= 1.0.3 =
* New: a built-in **SecurityWP → Traffic** view for sites not on the INI WP platform — totals, top offender IPs, suspicious paths, recent suspicious requests, suggested blocks, and a 1h / 24h / 7d window selector. Renders the same data the platform pulls.
* New: **IP blocking** — block an offender (or any IP) straight from the Traffic view; blocked IPs get a 403 early in the request. Uses the spoof-resistant client IP, runs independently of the traffic monitor, and refuses to block your own current IP (no self-lockout). Admins always bypass.

= 1.0.2 =
* New: the platform state endpoint (secwp/v1/state) now includes an aggregated `traffic` summary — totals, top offender IPs, suspicious paths, a recent sample, and suggested block rules — for the INI WP control panel's Traffic tab. Reports `enabled:false` when the traffic monitor is off. Honours an optional `?hours=` look-back window hint. Additive (schema_version unchanged).

= 1.0.1 =
* New: "Require login for REST API" now has a per-namespace public whitelist — tick which registered REST namespaces stay public (e.g. a headless front-end, oEmbed, a contact-form endpoint); everything else requires login. Strict by default (nothing public until ticked).
* Safety: the INI WP family REST namespaces are always exempt and can never be blocked, so the control panel (wp.ini.bg) and integrating plugins can't be locked out. Family membership is read from the connector's registry (iniwp_family_rest_namespaces) when present, with a safe built-in fallback when standalone; SecurityWP self-registers secwp/v1. The whitelist UI shows the always-public namespaces read-only.

= 1.0.0 =
* Initial release. Security / head-cleanup / SEO-privacy hardening extracted
  into a standalone plugin, plus the INI WP platform-state endpoint.
