=== SEO Ops ===
Contributors: cultureddigital
Requires at least: 6.5
Tested up to: 6.7
Requires PHP: 8.1
Stable tag: 1.4.1
License: GPLv2 or later

SEO client management and delivery system: clients, strategies, campaigns, tasks, approvals, reporting and a client portal.

Nothing to configure: the plugin creates its own encryption key. An optional SEOOPS_ENCRYPTION_KEY in wp-config.php is supported (see docs/DEPLOY.md).

== Changelog ==

= 1.4.1 =
* **Branded invitation email.** Portal and staff invitations are now a clear, branded email with a **Set your password** button and the sign-in address, sent through whatever mail setup the site uses (for example an SMTP plugin), instead of the plain WordPress "new user" message.
* **Resend invite.** Each portal user has a **Resend invite** link that sends a fresh set-password link.
* **Remove portal user.** A **Remove** link on each portal user ends their access and deletes their login (staff accounts are never deleted). Their approvals and comments stay in the history.
* **Portal-branded sign-in.** The sign-in and set-password screens for client users now read as the client portal: the agency name (and logo, if the theme has one), "Welcome, <name>", the client's name and plain wording, instead of the generic WordPress screen.
* **No more silent failures.** If the invitation email cannot be sent, the app says so (the user is still created) so it can be resent once email is fixed.
* Portal-user actions (approver, disable, enable) now show the real error if one happens instead of doing nothing.
* The Screaming Frog import dialog said "issues in undefined" instead of the file name.

= 1.4.0 =
* **Automatic plugin updates.** Sites running the plugin see "update available" on the WordPress Plugins screen and update with one click (or with WordPress's automatic updates, if switched on), from a signed update file hosted on seoclientplugin.com. Free and Premium sites update the same way: no licence is needed to receive an update.
* **Signed updates.** The update file is signed with a private key that only the publisher holds, and the plugin carries the matching public key. An update file that is missing, altered or signed by anyone else is ignored. The package must be on the same host as the update file, and the downloaded file must match the checksum in the signed file before WordPress unpacks it.
* **Privacy.** The check sends no site address and no licence key: just a plain request with the plugin version as its user agent. The answer is cached for 12 hours (an hour after a failed check), so it never slows the admin down. Switch checks off with `define( 'SEOOPS_DISABLE_UPDATE_CHECK', true );` in `wp-config.php`.
* Publisher tooling: `node bin/release-keys.js` (one-time signing key), `node bin/release.js` (builds the signed release in `dist/release`), and `docs/RELEASING.md`.
* Sites on 1.3.x or earlier need this one version installed by hand; from then on updates arrive automatically.

= 1.3.0 =
* **Premium licence (Lemon Squeezy).** **Settings > Licence** activates a Premium key for this site, checks it, shows the plan, the sites using the key and when it was last checked, and deactivates it to free the activation. The key is stored encrypted and is never returned (only its last four characters). A key is only accepted if it was issued for this store and product, so a key bought anywhere else cannot unlock Premium.
* **The Free plan.** Free allows up to 3 active clients (prospect, onboarding, active, paused and at risk; completed and archived clients do not count) and the Screaming Frog import. Adding a fourth, or moving a completed client back to an active status over the limit, is refused with a clear message and a link to the plans.
* **Premium features are checked on the server**: AI drafting, the OpenAI and Gemini providers, Search Console, GA4, Business Profile, Semrush and Ahrefs (connecting, testing, signing in, and refreshing their data, including the daily job). **Settings > Integrations** shows a Premium lock on them and a button to the Licence screen instead of letting a click fail. Disconnecting is always allowed.
* Daily licence re-check. If Lemon Squeezy cannot be reached, the last good check is trusted for 7 days; if it answers that the licence is expired, disabled or invalid, Premium switches off straight away. A copy of the database on a different site address is not licensed until the key is activated there.
* REST: `GET /licence`, `POST /licence/activate`, `/licence/refresh`, `/licence/deactivate` (administrators only).
* Switching Premium off never deletes or hides anything. Clients above the Free limit stay visible and editable; only adding new active clients and the Premium features stop.
* `src/Licensing/Config.php` holds the Lemon Squeezy store and product IDs the licence must belong to. They are 0 until filled in, and activation is refused while they are 0.
* Tested against a mocked licence service written from Lemon Squeezy's documentation (unit tests, and a browser test of the Licence screen). Verify with a real test-mode purchase before release.
