=== WPExit ===
Contributors: wpexit
Tags: static site, export, migration, html, headless
Requires at least: 5.9
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 0.2.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Move your site off WordPress and PHP with WPExit: a fast, secure static version of your site on managed hosting, with the same URLs and AI-assisted editing when you need changes. This companion plugin collects an inventory, pairs the site with WPExit and lets the WPExit crawler read a signed URL manifest and content export.

== Description ==

WPExit turns a WordPress site into a fast, static HTML site hosted without PHP. The heavy lifting (crawling, verification, hosting) happens on WPExit servers. This plugin is intentionally thin and does only five things:

* **Inventory** - counts plugins, themes, post types, taxonomies, media, menus, users, comments, shortcodes, forms and a handful of "dynamic behaviour" signals. Nothing is sent anywhere until you click "Send to WPExit".
* **Pairing** - a one-time code links this site to your WPExit account.
* **Manifest** - a paginated list of every public URL (plus redirect rules) so the crawler never misses a page.
* **Content export** - rendered and raw post content, menus and a safe allowlist of options.
* **Crawler mode** - when a request is signed by WPExit, caching, minification, lazy loading, the admin bar and head noise (emoji scripts, oEmbed discovery, RSD, generator tag, shortlinks, speculation rules) are disabled so the crawl is clean.

All crawler-facing REST endpoints require an HMAC signature derived from a per-site secret issued at pairing time. The secret is stored in `wp_options` and never printed anywhere.

== Privacy and external services ==

This plugin contacts nobody until an administrator clicks **Connect to WPExit** (or "Pair now" under Advanced), with one exception: the update check described below. After connecting it communicates only with the WPExit control plane shown on its settings page (the default is set at release time and can be changed).

What is sent, and when:

* On connect: the site URL, the pairing code, the plugin version, and the site administrator's email address and site name, so WPExit can create the owner's portal account and email a sign-in link.
* When you send an inventory: WordPress and PHP versions, the active theme, the list of installed plugins and whether each is active, public post type and taxonomy counts, menu names, media count, form plugin names and their notification addresses, shortcodes in use, whether search or private/protected posts exist, custom database table names, and public URL counts. No post content, no comments, no user accounts or passwords are included.
* When WPExit crawls your site after pairing: it requests your public pages like any visitor, authenticated with a per-site secret so caching plugins are bypassed. On request it can also read a structured export of published posts and pages (the same content any visitor can see) and your menus and a small allowlist of options such as the site title.

* Update check: at most once every 12 hours, when WordPress looks for plugin updates, the plugin asks the control plane for its latest release (`GET {control}/api/plugin/update`). The request carries only the plugin version and the site URL (in the User-Agent header). Updates are installed from the control plane's download URL through the normal Plugins screen, never silently, unless you turned WordPress auto-updates on for this plugin. Add `define( 'WPEXIT_DISABLE_UPDATES', true );` to `wp-config.php` to disable the check entirely.

Nothing else is sent on a schedule and nothing is sent to anyone other than the control plane you connected to. Disconnecting deletes the pairing credentials from this site. Uninstalling removes every option the plugin stored. WPExit's privacy policy is linked from the settings page.

== Installation ==

1. Upload the `wpexit` folder to `/wp-content/plugins/` or install the zip from the Plugins screen (Add New > Upload Plugin).
2. Activate the plugin.
3. Go to **Settings > WPExit** and click **Connect to WPExit**. The plugin pairs, sends the inventory and opens WPExit so you can confirm your email and sign in to your portal.
4. Advanced (manual) path: copy the pairing code into the WPExit app, click **Pair now**, then **Run inventory now** and **Send to WPExit**.

Later releases are offered on **Plugins > Installed Plugins** like any other plugin; **Settings > WPExit > Check for updates** asks right away.

== Frequently Asked Questions ==

= Does this plugin send data automatically? =

No. Nothing leaves your server until you click "Pair now" or "Send to WPExit". The signed REST endpoints only respond to requests carrying a valid signature from WPExit.

= Does it slow my site down? =

No. On normal front-end requests the plugin only checks for two request headers. The inventory runs on demand and is designed to finish inside a few seconds on shared hosting.

= What does uninstall remove? =

All `wpexit_*` options (pairing code, tokens, secret, last inventory, version advice) and the plugin's transients.

= How do updates work without WordPress.org? =

The plugin asks the WPExit control plane for the latest release (at most every 12 hours) and hands the answer to WordPress' own update screen, so you update it exactly like any other plugin. The package is only accepted from an https URL or from the control plane's own host. To switch this off add `define( 'WPEXIT_DISABLE_UPDATES', true );` to `wp-config.php`.

= Why does pairing say my plugin is too old? =

WPExit sets a minimum plugin version for pairing when the manifest or export format changes. Update from Plugins > Installed Plugins (or Settings > WPExit > Check for updates) and connect again. If you are merely behind the latest version, pairing succeeds and a notice reminds you to update.

== Changelog ==

= 0.2.0 =
* One-click **Connect to WPExit**: pairs, sends the inventory and opens the WPExit portal sign-in.
* Update channel: the plugin checks WPExit for new versions (at most every 12 hours) and installs them from the Plugins screen. Define `WPEXIT_DISABLE_UPDATES` to turn this off.
* Minimum version check at pairing: WPExit tells the plugin when it is too old to pair, and the settings page shows the current and latest version with a "Check for updates" button.

= 0.1.0 =
* Initial release: inventory, pairing, status/manifest/export REST endpoints, crawler mode.
