=== Site Add-on Watchdog ===
Contributors: aaronhsieh
Tags: security, plugins, monitoring, notifications
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 8.1
Stable tag: 1.8.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Monitor installed plugins for security notices, outdated releases, and optional version-aware WPScan disclosures.

== Description ==

Site Add-on Watchdog keeps an eye on your site's plugins and warns you when:

* Your installed version is two or more minor releases behind the directory build.
* The official changelog mentions security or vulnerability fixes.
* (Optional) WPScan lists open CVEs for the plugin when you provide your own API key.

The plugin runs on a schedule you control—choose daily, weekly, a twenty-minute testing cadence, or rely on manual scans—and stores results locally. To compare public versions and changelogs, Watchdog sends one plugin slug at a time to WordPress.org and caches the response. WPScan lookups and outgoing notifications remain opt-in.

=== Privacy first ===

* Risk processing and storage stay on your site; Watchdog does not send telemetry, site content, or user data.
* WordPress.org receives one request for each installed plugin slug so Watchdog can retrieve public version and changelog data.
* WPScan receives one plugin-slug lookup at a time only when you add your personal API token.
* Notification channels are opt-in and send the detected plugin risks to the destinations you configure.

=== External services ===

Watchdog uses the following external services under the stated conditions:

* **WordPress.org Plugin API (required for directory comparisons):** During a scan, Watchdog sends each installed plugin slug separately to retrieve its public version and changelog. No site content or user data is included. See the [WordPress.org service](https://api.wordpress.org/) and [privacy policy](https://wordpress.org/about/privacy/).
* **WPScan API (optional):** When you save a WPScan API token, Watchdog sends that token as authorization and submits one plugin slug at a time to retrieve vulnerability records. See [WPScan](https://wpscan.com/), its [terms](https://wpscan.com/terms/), and the applicable [Automattic privacy policy](https://automattic.com/privacy/).
* **Notification destinations (optional):** When you enable Email, Discord, Slack, Microsoft Teams, or a custom webhook, Watchdog sends the alert to the address you configure. Alerts can include plugin names, installed and available versions, risk or vulnerability details, and links back to your WordPress administration area. Those transmissions are governed by your mail provider or destination service; review the applicable policies for [Discord](https://discord.com/terms) ([privacy](https://discord.com/privacy)), [Slack](https://slack.com/terms-of-service) ([privacy](https://slack.com/trust/privacy/privacy-policy)), or [Microsoft](https://www.microsoft.com/servicesagreement) ([privacy](https://privacy.microsoft.com/privacystatement)).

=== Admin tools ===

* Focused dashboard with risk summaries, searchable history, delivery health, and manual actions.
* Ignore list to suppress noisy plugins.
* Validated notification settings with a save-and-test action for every channel.

=== Notifications ===

* Email: send to one or more recipients separated by commas, semicolons, or spaces; site administrators are always included.
* Discord: post to a channel via webhook.
* Slack: connect via an incoming webhook to post alerts into any workspace channel.
* Microsoft Teams: send notices through Teams Workflows or an existing Incoming Webhook connector.
* Generic webhook: post JSON payload to any endpoint you control, with optional HMAC signatures. Failed deliveries are logged and highlighted on the Watchdog admin screen so you can reconfigure or resend manually.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/` or install via the admin dashboard.
2. Activate the plugin through the 'Plugins' menu in WordPress.
3. Open the top-level **Watchdog** menu in the WordPress sidebar to review the risk table and adjust notifications (older versions or custom admin menu placements may still show under Tools → Watchdog).
4. (Optional) Add your WPScan API key in the settings to fetch vulnerability intelligence.

== FAQ ==

= Does this plugin share my list of installed plugins? =

Risk processing and storage happen locally, but version comparison requires Watchdog to query WordPress.org once for each installed plugin slug. If you add a WPScan API token, each plugin slug is also queried against WPScan. Watchdog does not send site content, user data, or telemetry. Notification channels only send detected plugin risks when you explicitly configure and enable them.

= How do I get a WPScan API key? =

Register for a free account at [wpscan.com](https://wpscan.com/) and copy the API token from your profile. Paste the token into the Watchdog settings page to enable vulnerability lookups.

= How do I configure Slack or Microsoft Teams notifications? =

Slack requires an Incoming Webhook URL that you can generate from your workspace's App Directory. For Microsoft Teams, create a workflow that starts when a webhook request is received, or use an existing Incoming Webhook connector. Paste the resulting HTTPS URL into Watchdog, enable the channel, then use its save-and-test button to verify delivery.

= Can I trigger scans manually? =

Yes. Use the "Run manual scan" button on the Watchdog admin page.

= How do I resend a failed notification payload? =

Open the Watchdog admin page and check the **Delivery health** section. If a notification fails, the payload is captured there with buttons to re-queue or download it.

= Where can I find the test suite? =

Tests and the `phpunit.xml.dist` configuration are available in the public repository but are excluded from the published plugin package. Clone the repo from GitHub to run the test suite locally with PHPUnit.

== Troubleshooting ==

=== Scheduled scans are not running ===

Watchdog relies on WP-Cron to trigger scheduled scans and notifications. If you have set `DISABLE_WP_CRON` to `true` or your site receives very little traffic (so WP-Cron rarely runs), configure a system cron job to call either `wp-cron.php` or the plugin's REST endpoint. The admin **Delivery health** panel shows the endpoint and generated secret. Send the secret in an HTTP header so it does not appear in access logs; a typical example looks like this:

`curl -X POST -H "X-Watchdog-Cron-Key: YOUR_GENERATED_SECRET" https://example.com/wp-json/site-add-on-watchdog/v1/cron`

Testing-mode notifications also rely on this trigger, so be sure your cron job is running when validating delivery.

== CLI Usage ==

Watchdog bundles a WP-CLI command so you can run scans outside of the WordPress admin. All examples below assume the command is executed from a shell where `wp` (WP-CLI) is available.

`wp watchdog scan [--notify=<bool>]`

* `--notify` (optional): Accepts `true` or `false` (defaults to `true`). When set to `false`, Watchdog will skip any configured email or webhook notifications and only record the scan locally.

Examples:

* Run a scan and send notifications (default): `wp watchdog scan`
* Run a scan silently (skip notifications): `wp watchdog scan --notify=false`

Recommended workflow: on CI/CD platforms, add a job step that boots your WordPress/WP-CLI container, runs pending database migrations if needed, and then calls `wp watchdog scan --notify=false` to verify the plugin state without spamming production channels. Promote to production by rerunning the same command with notifications enabled when you are ready to alert your team.

== Development ==

The development repository is available on GitHub: https://github.com/happyloa/site-add-on-watchdog. Clone it locally to review the source or run the test suite.

== Changelog ==

= 1.8.1 =
* Filter WPScan disclosures against the installed plugin version so resolved vulnerabilities are not reported as active.
* Pause additional WPScan requests after rate-limit or temporary server responses.
* Require a genuine POST for the external Cron endpoint, reject method overrides, and support secret delivery through an HTTP header while retaining legacy query-key compatibility.
* Correct external Cron and privacy documentation, and harden the local Cron fallback.
* Add regression coverage for version-aware vulnerability filtering, API cooldowns, and Cron authentication.

= 1.8.0 =
* Refresh the admin dashboard with overview cards, section navigation, responsive settings, and clearer delivery controls.
* Isolate plugin bootstrapping, message formatting, risk sorting, and scan orchestration into focused services.
* Validate and test Email, Discord, Slack, Teams, and generic webhook settings before delivery.
* Update notification payloads and limits for current Slack, Discord, and Microsoft Teams webhook behavior.
* Use safe WordPress HTTP requests, redact secrets from errors, and contain bootstrap or provider failures.
* Cache WordPress.org lookups, preserve prior reports on scan failure, and defer the first remote scan after activation.
* Register recurring schedules after WordPress initializes translations to prevent WordPress 6.7+ debug notices.
* Preserve external Cron secrets across requests and upgrades so configured scheduler URLs remain valid.
* Declare compatibility with WordPress 7.0 and require PHP 8.1 or newer.

For earlier releases, see the full [GitHub changelog](https://github.com/happyloa/site-add-on-watchdog/blob/main/CHANGELOG.md).

== Upgrade Notice ==

= 1.8.1 =
External Cron calls must now use POST. Update existing GET jobs before upgrading; legacy `?key=` authentication remains temporarily available only for POST requests, while new jobs should use the `X-Watchdog-Cron-Key` header.
