=== Vybe Eye Connector ===
Contributors: vybefind
Tags: seo, schema, redirects, automation, vybefind
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Securely applies VybeFind-approved SEO changes to this WordPress site — with a full change log, drift detection, and one-click rollback.

== Description ==

Vybe Eye Connector is the WordPress side of the VybeFind Execution Layer. It
requires an active VybeFind account (https://vybefind.com) — the plugin is the
site-side agent for that service and does nothing on its own until paired. Once
paired with your VybeFind workspace, it pulls the changes your team has approved
in the Execution console and applies them in place:

* Title tags and meta descriptions — via Yoast, Rank Math, or All in One SEO
  when present, or a native fallback when no SEO plugin is installed.
* JSON-LD structured data — injected into the page head, idempotently.
* Image alt text.
* Internal links — inserted into the target post content, de-duplicated.
* 301 redirects.

Every applied change is recorded locally with a hash of the value it wrote, so
the plugin can detect **drift** (something later changed the value out from
under it) and offer **one-click rollback** to the previous value.

== How pairing works ==

1. In VybeFind, open **Execution** and click **Generate pairing code** for your
   site.
2. In WordPress, go to **Settings → Vybe Eye Connector**, paste the one-time code,
   and click **Pair site**. That is the only field to fill in — the plugin
   connects to VybeFind at https://vybefind.com by default. (Agency or
   self-hosted workspaces can point at a different host under **Advanced**.) The
   plugin generates a local keypair, exchanges the code for a per-site bearer
   token, and stores it privately (never shown again).
3. The plugin polls VybeFind every 15 minutes (WP-Cron). Each poll pulls pending
   changes as an HMAC-signed envelope, verifies the signature, applies each
   change, and reports the outcome back.

== External services ==

This plugin connects to the VybeFind platform (https://vybefind.com), the SaaS
service it is the WordPress client for. An active VybeFind account is required;
the plugin performs no external communication until you pair it with a workspace.

When and why it connects:

* **At pairing (once, when you click "Pair site").** The plugin sends your
  one-time pairing code, a locally generated public key, and your WordPress
  version to `https://<your-platform-host>/api/wp/pair` in exchange for a
  per-site bearer token. The platform host is the URL you paste at pairing
  (VybeFind-hosted by default); all later requests are pinned to that host.
* **Every 15 minutes (WP-Cron poll).** The plugin requests pending approved
  changes from `/api/wp/changes` using the bearer token. No site content is
  uploaded on this request — it only pulls the change instructions your team
  approved in VybeFind.
* **After applying each change.** The plugin reports the outcome
  (applied / drifted / rolled_back / failed) and a hash of the value it wrote
  to `/api/wp/changes/<id>/status`. It does not transmit page content, visitor
  data, or personal data.

Data sent: pairing code, generated public key, WordPress version, change IDs,
and per-change outcome hashes. Data received: the SEO change instructions
(titles, meta descriptions, JSON-LD, alt text, internal links, redirects) you
approved in your VybeFind workspace.

Your use of the VybeFind service is governed by its terms and privacy policy:

* Terms of Service: https://vybefind.com/legal/terms
* Privacy Policy: https://vybefind.com/legal/privacy

== Security ==

* The per-site bearer token and the signing keypair are stored as non-autoloaded
  options and never printed back into the admin UI.
* Every changes envelope from the platform is HMAC-verified before anything is
  applied — unsigned or tampered payloads are refused (fail-closed).
* All admin actions are capability- (manage_options) and nonce-guarded.
* Outbound requests only ever go to the platform URL saved at pairing.

== Changelog ==

= 1.0.1 =
* Security/hardening: JSON-LD schema is now escaped late on output via
  wp_json_encode() with JSON_HEX_TAG/HEX_AMP/HEX_APOS/HEX_QUOT so it can never
  break out of the <script> tag, and only well-formed JSON objects are stored
  (malformed input is rejected on write). Addresses the plugin-review escaping note.

= 1.0.0 =
* Initial release: pairing handshake, 15-minute pull-apply loop, Yoast/RankMath/
  AIOSEO adapters + native fallback, JSON-LD injection, alt text, internal links,
  redirects, local change log, drift detection, and one-click rollback.
