=== NoyaCare ===
Contributors: noyanahmed
Tags: maintenance, updates, backup, rollback, reports
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.9.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Safe unattended updates: a restore point before every update, a check of the live site afterwards, automatic rollback, and a client report.

== Description ==

NoyaCare is for agencies and freelancers who look after client sites and need updates to be safe and provable. Every item goes through the same steps:

1. **Restore point** — the plugin or theme folder is archived and the option rows it owns are saved.
2. **Update** — the item is installed on its own, never in a batch, so a failure always has a clear cause.
3. **Check** — key pages are loaded over real HTTP and compared with before the run: status codes, PHP fatal errors on those pages or in the updated code, a page that shrinks or stops half-way, and new PHP error-log entries.
4. **Roll back** — if the site broke, the restore point is put back automatically and the run carries on (or stops, your choice).
5. **Report** — the client gets an HTML e-mail, with a PDF when the backup folder is protected. Every run and every item has its own reference number.

= Why it is different =

* **A restore point before every item**, small and fast even on shared hosting: one folder and its option rows. A full database dump is optional.
* **The live site is checked over HTTP**, the way a visitor sees it — not from inside the update process.
* **Careful rollback rules.** Only a problem a visitor would notice counts as a failure. Slowdowns and deprecation notices are reported, never rolled back.
* **Background runs that survive shared hosting**: small steps, a watchdog, a live progress bar and a cancel button.
* **Quarantine.** A version that broke the site stays held until you release it.
* **Security fixes first.** With a WPScan or Patchstack key, an update that fixes a known vulnerability goes in straight away and leads the client report.
* **Website speed** from Google PageSpeed Insights and NoyaCare's own checks, which also work on local sites, kept as a trend.
* **No bloat.** No bundled libraries and no build step.

= NoyaCare Pro =

NoyaCare is complete on its own. The separate NoyaCare Pro add-on adds uptime monitoring, AI analysis of failed runs, GTmetrix, scheduled speed tests and white-label reports.

= Scheduling =

Automatic runs are off until you choose a schedule, and WP-Cron only runs on visits. With real cron, run maintenance from the command line:

`0 3 * * 2 cd /path/to/site && wp noyacare run --quiet`

or keep NoyaCare's schedule and call WP-Cron every few minutes:

`*/5 * * * * cd /path/to/site && wp cron event run --due-now --quiet`

= WP-CLI =

`wp noyacare status|run|health|speed|quarantine|backups|restore|prune|access|report` — `wp help noyacare <command>` shows the options of each, such as `run --dry-run`.

= REST API =

Read-only, authenticated with an application password over HTTPS: `GET /wp-json/noyacare/v1/status`, `…/updates`, `…/runs/<run-uid>`, `…/performance`. No run starts from outside.

= For developers =

Filters and actions include `noyacare_loaded`, `noyacare_run_tasks`, `noyacare_report_data`, `noyacare_capability` and `noyacare_run_finished`. Like WordPress's own, NoyaCare's requests to the site skip TLS certificate checks, which local and staging sites would fail; `noyacare_sslverify` turns them on.

== External services ==

NoyaCare connects to these services only when the feature that needs them is used.

* **Google PageSpeed Insights** — when you start a speed test (dashboard, Website speed screen, `wp noyacare speed`) or test the connection: each tested page's address, the device (mobile or desktop) and your optional API key go to Google, which then loads the page like a visitor. [Terms of service](https://developers.google.com/terms), [privacy policy](https://policies.google.com/privacy).
* **WPScan** — only when vulnerability checks use WPScan: whenever NoyaCare looks at pending updates (dashboard, runs, WP-CLI), the slugs and installed versions of the plugins, themes and WordPress release with an update waiting go with your API token. Answers are kept for 12 hours. [Terms of service](https://wpscan.com/terms/), [privacy policy](https://automattic.com/privacy/).
* **Patchstack** — only when vulnerability checks use Patchstack: the same slugs and versions, with your API key. [Terms and conditions](https://patchstack.com/terms-and-conditions/), [privacy policy](https://patchstack.com/privacy-policy/).
* **WordPress.org** — when a WordPress core update breaks the site, the previous release is downloaded from downloads.wordpress.org to put it back; the request names only the version and language. [Privacy policy](https://wordpress.org/about/privacy/).

Suggested wording for the site's privacy policy appears under **Settings → Privacy**.

== Installation ==

1. Install and activate NoyaCare from **Plugins → Add New**.
2. In **NoyaCare → Settings**, choose the schedule, the pages to check and the report recipients, then send a test report.
3. On Nginx, add the rule from "Where are restore points stored?" below.

Updates need direct file access, or `FS_METHOD` and the `FTP_*` constants in `wp-config.php`: an unattended run cannot answer a credentials prompt.

== Frequently Asked Questions ==

= What happens if a run dies half way through? =

A watchdog resumes a background run within about five minutes; the item being updated is put back to its restore point and the run carries on. A run with no progress for 30 minutes is stopped cleanly: the maintenance page comes down and the report still goes out.

= Why is an update held? =

"Held — version X broke this site": that version was rolled back before, so it is quarantined. Release it from the dashboard or with `wp noyacare quarantine release <slug>`; the next run tries it again. Newer versions are not affected.

"Needs PHP 8.2 or newer": the new version needs a newer PHP or WordPress (WordPress itself: PHP or MySQL) than this site has, so WordPress would not install it either. WP-CLI and system cron go by their own PHP when it is older. It stays held, even with "install everything", until the server or WordPress is updated.

= Where are restore points stored? =

In a randomly named folder inside `wp-content/uploads/noyacare-backups/`, closed by `.htaccess` (Apache, LiteSpeed) and `web.config` (IIS). A daily test asks the web server for harmless test files there; Restore points shows the result. **Nginx ignores `.htaccess`**: add this to the `server` block:

`location ^~ /wp-content/uploads/noyacare-backups/ { deny all; }`

Until the test finds the folder closed, no restore points are made, and updates that need one are skipped. A redirect or an unclear answer does not count as closed. A folder found open loses its database backups and stored reports at once; restore points stay for undoing updates. The dashboard counts what stays.

Where PHP runs as the account owning the site's files (most shared hosting), only that account can read these files (0600, in 0700 folders); filter `noyacare_private_modes`.

= Does a rollback undo my orders or posts? =

No. It puts back the item's files and the option rows that changed since the restore point (a restore by hand: only the item's own). Its database tables (a WooCommerce database update, say), orders, posts and other plugins' settings stay as they are, so hold major versions of plugins that migrate data. NoyaCare never imports a full database backup.

= Can I keep other administrators out of NoyaCare? =

Yes, under **Settings → Access**. You stay on the list; changes are logged and e-mailed to the managers. Locked out? Run `wp noyacare access reset`. Any administrator can still deactivate plugins.

= Who can run updates? =

In the admin: administrators who manage NoyaCare and may update plugins, themes and WordPress. Where updates run, only they change the schedule, the update policy and the restore point and check settings, and a run installs only what its starter may update. WP-CLI has no WordPress user: whoever can run it on the server can start a run or a restore. A schedule runs once such an administrator has switched it on. Nothing is installed where `DISALLOW_FILE_MODS` is set; on multisite, updates run from the main site.

= What if the salts change? =

API keys are encrypted with a key made from `AUTH_KEY` and `SECURE_AUTH_SALT`, or `NOYACARE_ENCRYPTION_KEY`. After new salts, enter the keys again.

= Can I manage several sites from one dashboard? =

No. Nothing outside a site can update it or start a run there. The read-only REST API lets a dashboard of your own show how sites are doing.

== Screenshots ==

1. The dashboard: pending updates, the last and next run, and what protects the site.
2. A run in progress, with live progress and the log.
3. The client report e-mail.
4. The Website speed screen.
5. Settings, one section at a time.

== Changelog ==

= 1.9.2 =
* Fix: a fatal error counts against an update only when NoyaCare's check hit it or the updated code raised it, and every run sees it; others are only listed.
* Fix: updates that need a newer PHP, WordPress or MySQL than the site has are held.
* Security: checks carry a signed pass valid for ten minutes, not a fixed secret, and page caches never keep their answers.
* Security: only an administrator who may update changes the restore point and check settings, also with every update kind off.
* Security: restore points, backups and reports are private to the site's account where PHP runs as it; a folder found open loses its database backups and reports at once.
* Fix: restore points are not deleted while a run or a restore may need them.
* Privacy: diagnostics hide query values, tokens and the backup folder name.
* Dev: `requires_*` on pending updates; filters `noyacare_fatal_roots`, `noyacare_private_modes`.

Older versions are listed in `changelog.txt`.

== Upgrade Notice ==

= 1.9.2 =
A visitor's error in other code no longer rolls updates back; updates this server cannot run are held; backups are better protected.
