{"id":327828,"date":"2026-07-02T15:08:28","date_gmt":"2026-07-02T15:08:28","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/omnihealth-deep-site-auditor\/"},"modified":"2026-07-02T15:08:03","modified_gmt":"2026-07-02T15:08:03","slug":"pressvitals-site-auditor","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/pressvitals-site-auditor\/","author":148410,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.2.6","stable_tag":"1.2.6","tested":"7.0","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"PressVitals Site Auditor","header_author":"merolhack","header_description":"A headless-first diagnostic engine featuring 22+ proactive probes for performance, security, and DB health \u2014 extensible to 48+ via REST API and custom filters.","assets_banners_color":"031a31","last_updated":"2026-07-02 15:08:03","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/pressvitals-site-auditor\/","header_author_uri":"https:\/\/merolhack.github.io\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":24,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq"],"tags":{"1.2.6":{"tag":"1.2.6","author":"merolhack","date":"2026-07-02 15:08:03"}},"upgrade_notice":{"1.2.0":"<p>Adds update\/version, user-enumeration, and orphaned-table probes (29 total).<\/p>","1.1.0":"<p>Adds three new security\/database probes (.env on disk, wp-config.php permissions,\ncore tables present).<\/p>","1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3594207,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3594207,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3594207,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3594207,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.2.6"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"The admin report grouped by category with the summary box.","2":"The settings page (thresholds and alert email).","3":"Initial WordPress.org SVN release: includes directory branding assets (icons, banners) and automated SVN deployment CI pipeline.","4":"Documentation updates including the LLM Wiki addition for AI agents.","5":"Phase 4 CI complete: Expanded unit tests for network and DB probes, WP version matrix, and added strict PHPCS &amp; Plugin Check CI gates.","6":"Phase 3 UX complete: Added Run Now button, JSON\/CSV exports, and Slack webhook alert channel support.","7":"Add composer make-pot script and sample Spanish (es_ES) locale translation.","8":"Phase 1 of engineering roadmap complete: data migrations and GitHub update checker implemented.","9":"Implement the final P3 probes: https_mixed_content and rest_api_reachable.\nenumeration exposure (<code>?author=N<\/code> + REST users), and non-core\/orphaned database\ntables (filterable via <code>pvsa_known_tables<\/code> \/ <code>pvsa_orphan_tables_warn<\/code>). Total\nbuilt-in probes: 29.","10":"Add 3 security\/database probes: <code>.env<\/code> file detected on disk (with permission\ncheck), wp-config.php permissions, and core database tables present. Total\nbuilt-in probes: 25.","11":"Initial release: pluggable probe engine (<code>pvsa_registered_checks<\/code> filter), 22\nbuilt-in probes across performance, security, deliverability and database\nhealth, categorized admin report with summary box, daily cron with email\nalerts, severity tiers with a worst-of verdict, and <code>\/ping<\/code> + token-gated\n  \/report REST endpoints."}},"plugin_section":[],"plugin_tags":[5603,23853,600,151481,29148],"plugin_category":[54],"plugin_contributors":[269902],"plugin_business_model":[],"class_list":["post-327828","plugin","type-plugin","status-publish","hentry","plugin_tags-monitoring","plugin_tags-rest-api","plugin_tags-security","plugin_tags-site-health","plugin_tags-uptime","plugin_category-security-and-spam-protection","plugin_contributors-merolhack","plugin_committers-merolhack"],"banners":{"banner":"https:\/\/ps.w.org\/pressvitals-site-auditor\/assets\/banner-772x250.png?rev=3594207","banner_2x":"https:\/\/ps.w.org\/pressvitals-site-auditor\/assets\/banner-1544x500.png?rev=3594207","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/pressvitals-site-auditor\/assets\/icon-128x128.png?rev=3594207","icon_2x":"https:\/\/ps.w.org\/pressvitals-site-auditor\/assets\/icon-256x256.png?rev=3594207","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>PressVitals Site Auditor is a <strong>headless-first<\/strong> diagnostic engine. It runs a\nsuite of read-only probes across performance, security, deliverability and\ndatabase health, assigns each a severity tier, rolls them up into a worst-of\nverdict, and exposes the result where automation can actually consume it: a\ntoken-gated REST report, a daily cron with email alerts, and a categorized admin\ndashboard.<\/p>\n\n<p>It is <strong>dependency-free<\/strong> \u2014 no WooCommerce, no page builder, no other plugin\nrequired \u2014 and <strong>pluggable<\/strong>: every probe is registered through a filter, so the\n<strong>22+ built-in probes<\/strong> are just the starting point. The architecture is designed\nto scale to <strong>48+ probes<\/strong> in production; register your own via\n    pvsa_registered_checks.<\/p>\n\n<h4>How is this different from the built-in Site Health?<\/h4>\n\n<p>WordPress core's <strong>Tools \u2192 Site Health<\/strong> is excellent, but it is an <em>on-demand,\nadmin-only<\/em> tool: you open a screen, it runs its status tests, and the Debug tab\nprints a static environment dump for support. PressVitals is built for a different\njob \u2014 <strong>continuous, automated, machine-readable monitoring and auditing<\/strong>:<\/p>\n\n<ul>\n<li><strong>Headless \/ API-first.<\/strong> Core Site Health has no public report API. PressVitals\nexposes a no-auth <code>\/ping<\/code> liveness probe and a token-gated <code>\/report<\/code> JSON\nendpoint (HTTP <strong>503<\/strong> on a failing verdict) so an external uptime monitor,\nstatus page, or CI pipeline can read site health without logging in.<\/li>\n<li><strong>Scheduled + alerting.<\/strong> Core never runs on a schedule and never tells you\nwhen something breaks. PressVitals runs daily via WP-Cron and <strong>emails the admin\nwhen the verdict is <em>fail<\/em><\/strong>.<\/li>\n<li><strong>Severity tiers + worst-of verdict.<\/strong> Core labels results good\/recommended\/\ncritical. PressVitals assigns each probe a 1\u20135 severity tier and computes a\nsingle rolled-up verdict suitable for a green\/red status signal.<\/li>\n<li><strong>Probes core does not have.<\/strong> TLS <em>certificate-expiry countdown<\/em> (core only\nchecks that HTTPS works today), <code>.env<\/code>\/secret-file web exposure, a web-root\nstray-backup scanner, baseline security headers (HSTS \/ X-Frame-Options \/ \u2026),\nforced-HTTPS redirect, XML-RPC exposure, default-<code>admin<\/code>-username detection,\nSPF + DMARC email-DNS records, homepage indexability, and database-bloat\n(expired transients \/ revisions \/ spam) checks.<\/li>\n<li><strong>Pluggable + configurable.<\/strong> Core's tests are fixed. PressVitals lets any plugin\nor theme register probes via a filter and tune every threshold via filters.<\/li>\n<\/ul>\n\n<p>Think of it as the layer <em>on top of<\/em> Site Health: the same read-only philosophy,\nre-pointed at automation, alerting, and security\/ops auditing.<\/p>\n\n<h4>Built-in probes<\/h4>\n\n<p>PressVitals ships <strong>29 built-in probes<\/strong>, grouped by functional category:<\/p>\n\n<ul>\n<li><strong>Availability<\/strong> \u2014 database connectivity, homepage HTTPS reachability.<\/li>\n<li><strong>Security<\/strong> \u2014 <code>.env<\/code> not web-accessible (HTTP) and not exposed on disk,\nweb-root stray\/backup file scan, TLS certificate expiry, baseline security\nheaders, forced HTTPS, XML-RPC exposure, no default <code>admin<\/code> user,\nwp-config.php permissions, user-enumeration exposure, error-display off.<\/li>\n<li><strong>Errors<\/strong> \u2014 error-log size, recent PHP fatal errors.<\/li>\n<li><strong>Database<\/strong> \u2014 core tables present, non-core\/orphaned tables, autoloaded-options\nsize, database bloat.<\/li>\n<li><strong>Files<\/strong> \u2014 free disk space, uploads-directory writability, recent backup.<\/li>\n<li><strong>Email<\/strong> \u2014 SPF + DMARC DNS records for the sending domain.<\/li>\n<li><strong>SEO<\/strong> \u2014 homepage is indexable (not noindex).<\/li>\n<li><strong>Performance<\/strong> \u2014 PHP memory limit, persistent object cache.<\/li>\n<li><strong>Environment<\/strong> \u2014 supported PHP version, WordPress core update available,\nplugin updates pending.<\/li>\n<\/ul>\n\n<h4>Extend it with your own checks<\/h4>\n\n<p>Probes are not hardcoded \u2014 the engine collects them from a filter, so any plugin\nor theme can register its own:<\/p>\n\n<pre><code>add_filter( 'pvsa_registered_checks', function ( array $checks ) {\n    $checks['my_queue_backlog'] = array(\n        'label'    =&gt; 'Job queue backlog',\n        'group'    =&gt; 'Performance',\n        'tier'     =&gt; 2,\n        'callback' =&gt; function () {\n            $pending = my_count_pending_jobs();\n            return $pending &gt; 1000\n                ? array( 'status' =&gt; 'warn', 'detail' =&gt; \"$pending jobs pending\" )\n                : array( 'status' =&gt; 'pass', 'detail' =&gt; \"$pending jobs pending\" );\n        },\n    );\n    return $checks;\n} );\n<\/code><\/pre>\n\n<p>A callback returns <code>array( 'status' =&gt; 'pass'|'warn'|'fail', 'detail' =&gt; '\u2026' )<\/code>.<\/p>\n\n<h4>Developer filters<\/h4>\n\n<ul>\n<li><code>pvsa_registered_checks<\/code> \u2014 register\/override probes.<\/li>\n<li><code>pvsa_setting_{key}<\/code> \u2014 override a stored threshold at read time.<\/li>\n<li><code>pvsa_alert_email<\/code> \u2014 change the failure-alert recipient.<\/li>\n<li><code>pvsa_http_timeout<\/code>, <code>pvsa_disk_free_min_bytes<\/code>, <code>pvsa_memory_min_bytes<\/code>,\n  pvsa_fatal_lookback_hours, <code>pvsa_fatal_scan_max_bytes<\/code> \u2014 tune environment probes.<\/li>\n<li><code>pvsa_ssl_warn_days<\/code>, <code>pvsa_ssl_fail_days<\/code> \u2014 TLS expiry thresholds.<\/li>\n<li><code>pvsa_backup_warn_days<\/code>, <code>pvsa_backup_fail_days<\/code> \u2014 backup-recency thresholds.<\/li>\n<li><code>pvsa_last_backup_timestamp<\/code> \u2014 report your last successful backup time (UNIX) so\nthe backup probe works with <em>any<\/em> backup plugin, host, or off-site service.<\/li>\n<li><code>pvsa_backup_plugins<\/code> \u2014 list of backup-plugin basenames recognised by presence.<\/li>\n<li><code>pvsa_max_expired_transients<\/code>, <code>pvsa_max_revisions<\/code>, <code>pvsa_max_spam_comments<\/code> \u2014\ndatabase-bloat thresholds.<\/li>\n<li><code>pvsa_known_tables<\/code> \u2014 full table names to treat as expected (silences the\nnon-core\/orphaned-tables probe for legitimate plugin tables).<\/li>\n<li><code>pvsa_orphan_tables_warn<\/code> \u2014 non-core table count above which the probe warns.<\/li>\n<li><code>pvsa_sending_domain<\/code> \u2014 domain used for the SPF\/DMARC lookup.<\/li>\n<\/ul>\n\n<h4>Compatibility<\/h4>\n\n<p>PressVitals has <strong>no plugin dependencies<\/strong> and runs on virtually any WordPress\ninstall \u2014 single-site or multisite, <strong>with or without<\/strong> WooCommerce, page builders,\nor a backup plugin. It calls only core WordPress APIs and guards every optional PHP\nfunction (<code>disk_free_space<\/code>, <code>stream_socket_client<\/code>\/OpenSSL, <code>dns_get_record<\/code>,\n    WP_Filesystem), degrading a probe to a neutral <em>pass\/skip<\/em> when something isn't\navailable rather than erroring. The backup probe is backup-agnostic: it reads\nUpdraftPlus directly, recognises other common backup plugins, and lets any other\nbackup solution (including host-level backups) report in via\n    pvsa_last_backup_timestamp.<\/p>\n\n<h3>Development<\/h3>\n\n<p>Two local workflows are scaffolded (both Docker-based; neither ships in the\npackage):<\/p>\n\n<p><strong>Automated tests \u2014 wp-env (recommended):<\/strong> requires Docker + Node.js.\n    npm -g install @wordpress\/env, then <code>wp-env start<\/code> and\n    wp-env run tests-cli --env-cwd=wp-content\/plugins\/pressvitals-site-auditor vendor\/bin\/phpunit.\nSwitch versions by editing <code>core<\/code> \/ <code>phpVersion<\/code> in <code>.wp-env.json<\/code> and running\n    wp-env start --update. Without Docker, run the suite the classic way:\n    composer install, <code>bin\/install-wp-tests.sh wordpress_test root '' localhost<\/code>,\n    composer test. A GitHub Actions workflow runs PHPUnit across PHP\n7.4 \/ 8.0 \/ 8.2 \/ 8.3.<\/p>\n\n<p><strong>Manual multi-version testing \u2014 docker-compose:<\/strong> <code>docker compose up -d<\/code> boots\nthree browsable installs at fixed WordPress x PHP combos (WP 6.7\/PHP 8.3,\nWP 6.4\/PHP 8.1, WP 6.3\/PHP 7.4) on ports 8083 \/ 8081 \/ 8074, each with the plugin\nmounted. See <code>docker-compose.yml<\/code> for details.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>pressvitals-site-auditor<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install\nit from the Plugins screen.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> menu in WordPress.<\/li>\n<li>Go to <strong>Tools \u2192 PressVitals Site Auditor<\/strong> to view the report and configure\nthresholds.<\/li>\n<li>(Optional) Copy the probe URL shown on that page into your external uptime or\nCI monitor.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20it%20replace%20the%20built-in%20site%20health%3F\"><h3>Does it replace the built-in Site Health?<\/h3><\/dt>\n<dd><p>No \u2014 it complements it. Site Health is the on-demand, admin-facing status screen;\nPressVitals adds headless REST reporting, scheduled monitoring with email alerts,\nseverity tiers, and security\/ops audit probes that core does not run.<\/p><\/dd>\n<dt id=\"does%20it%20require%20woocommerce%20or%20any%20other%20plugin%3F\"><h3>Does it require WooCommerce or any other plugin?<\/h3><\/dt>\n<dd><p>No. It runs on any standard WordPress install with no dependencies.<\/p><\/dd>\n<dt id=\"is%20the%20report%20endpoint%20safe%20to%20expose%3F\"><h3>Is the report endpoint safe to expose?<\/h3><\/dt>\n<dd><p>\/report requires either a logged-in administrator or a secret token compared\nwith <code>hash_equals()<\/code>. Rotate the token any time from the settings page. <code>\/ping<\/code>\nreturns only a tiny liveness payload with no sensitive data.<\/p><\/dd>\n<dt id=\"does%20it%20write%20to%20my%20database%20or%20files%3F\"><h3>Does it write to my database or files?<\/h3><\/dt>\n<dd><p>The probes are read-only. The plugin stores only its own options (settings, last\nreport, token) and reads log files solely from standard WordPress locations.<\/p><\/dd>\n<dt id=\"is%20it%20tested%3F\"><h3>Is it tested?<\/h3><\/dt>\n<dd><p>Yes. It ships with a PHPUnit suite built on the WordPress core test framework\n(<code>WP_UnitTestCase<\/code>) covering the check registry, the worst-of verdict aggregation,\ndefensive execution of a throwing\/malformed check, the settings filters, the\nbackup-recency filter, and the REST routes (public <code>\/ping<\/code>, token-gated <code>\/report<\/code>,\nand the 503-on-fail behaviour). Tests run in CI and locally via <code>composer test<\/code>\n(see <code>bin\/install-wp-tests.sh<\/code>); they are excluded from the distributed package and\nnever run on a live site. Activation performs only a lightweight requirements gate\n(PHP version + engine load), not the test suite.<\/p><\/dd>\n\n<\/dl>","raw_excerpt":"A headless-first diagnostic engine featuring 22+ proactive probes for performance, security, and DB health. Extensible via REST API and filters.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/327828","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=327828"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/merolhack"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=327828"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=327828"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=327828"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=327828"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=327828"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=327828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}