=== Keva Connector ===
Contributors: keva
Tags: ai, support, content-management, api
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.3.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connects your WordPress site to Keva for AI-powered content management.

== Description ==

Keva Connector provides a secure REST API that allows Keva to read and update content on your WordPress site. This enables Keva's AI to automatically fix and update website content based on support interactions.

**Features:**

* Secure token-based authentication
* HTTPS enforcement for production environments
* Rate limiting (100 requests per 5 minutes)
* Content CRUD operations (posts and pages)
* ACF (Advanced Custom Fields) support
* Health monitoring heartbeat endpoint
* Easy admin settings page

== Installation ==

1. Upload the `keva-connector` folder to `/wp-content/plugins/`
2. Activate the plugin through the 'Plugins' menu in WordPress
3. Copy the connector token shown in the activation notice
4. Go to your Keva dashboard → Settings → WordPress Sites
5. Click "Add WordPress Site" and enter your site URL and the connector token

== Frequently Asked Questions ==

= Where do I find my connector token? =

The token is shown once when you activate the plugin. If you need a new token, go to Settings → Keva Connector and click "Regenerate Token".

= Is it safe? =

Yes. Tokens are stored as hashed values (the same way WordPress stores passwords). All API requests require HTTPS in production. Rate limiting prevents abuse.

= What content can Keva manage? =

Currently, Keva can read and update posts and pages, including ACF custom fields if the ACF plugin is installed.

= Does it support custom post types? =

Currently only posts and pages are supported. Custom post type support is planned for a future release.

== Optional Configuration ==

Two constants can be set in `wp-config.php` to harden the connector further:

`define( 'KEVA_CONNECTOR_ALLOWED_IPS', [ '203.0.113.10', '203.0.113.0/24' ] );`
Only requests from these source IPs (exact or CIDR, IPv4) reach the
connector endpoints. Useful when Keva publishes a known egress IP range.
Leave undefined to allow any IP that has a valid token (default).

How to get Keva's egress IPs: Keva runs on Vercel. Vercel egress IPs
are NOT a public published list — they're per-project static IPs that
Keva must enable on its deployment (Vercel "Static IPs" feature, Pro
plan, $100/month per project, up to 3 regions). If Static IPs is NOT
enabled on the Keva backend, egress IPs are dynamic and an allowlist
isn't usable — rely on the token alone.

If you need an allowlist for compliance, contact Keva
(support@keva.support) — we'll either provision Static IPs or, for
enterprise tenants, set up Secure Compute (dedicated VPC with a
fixed IP pair, custom pricing).

`define( 'KEVA_CONNECTOR_TRUST_FORWARDED_FOR', true );`
Use the last hop of `X-Forwarded-For` instead of `REMOTE_ADDR` for both
the IP allowlist check and the rate limiter. Only enable this when
WordPress sits behind a reverse proxy that strips client-set XFF and
sets its own (e.g. Cloudflare, Nginx with a known upstream). Default
is `false` because XFF is otherwise attacker-controlled.

== Changelog ==

= 1.3.0 (2026-05-21) =
* Self-update: plugin now polls https://app.keva.support/plugins/keva-connector-info.json every 6 hours and surfaces "Update Available" in the WordPress Plugins page when a newer version is published. One-click update directly from WP admin — no more delete-and-reinstall.
* Self-update: registers a `plugins_api` handler so "View details" in the Plugins page shows a proper details modal with version, requirements, last updated, and changelog (pulled from this readme).
* Fixed: the plugin file header Version field was stuck at 1.0.0 since the initial release even as the internal KEVA_CONNECTOR_VERSION constant moved forward. WordPress reads the header to decide whether updates are needed, so sites were never seeing "Update Available." Header + constant are now kept in lockstep, enforced by the build script.

= 1.2.1 (2026-05-21) =
* UX fix: connection status panel is now ALWAYS visible at the top of
  the admin page (previously hidden during the post-activation welcome
  flow). Step 3 of the welcome instructions said "the status above will
  switch to Connected" — but there was no status above. Now there is.
* UX fix: the status panel auto-refreshes every 4 seconds via a new
  admin-ajax endpoint (wp_ajax_keva_status). The dot literally flips
  to green when Keva first authenticates, no page reload required.
  Polling pauses while the tab is hidden to save battery.
* UX fix: primary buttons (Copy / Open Keva dashboard) now use a slate
  gray (#1d2327) instead of WordPress's default blue. Matches the
  product's serious aesthetic; less generic.
* UX fix: dropped the 🎉 emoji from the welcome heading.

= 1.2.0 (2026-05-21) =
* UX: redesigned admin page with a welcome flow shown automatically on
  activation. Token displayed in a styled card with a one-click Copy
  button — no more dismissible notice that vanishes after 60 seconds.
  The new transient stores the freshly-generated token for 24 hours so
  admins can return to the page and still grab it.
* UX: real-time connection-status panel on Settings → Keva Connector.
  Shows whether Keva has contacted the site recently:
    - Connected (green pulse) — heartbeat in the last 10 minutes
    - Idle (purple) — last heartbeat > 10 min, normal if no tickets
    - Waiting for Keva (yellow) — token configured, paste it in Keva
    - Not configured (red) — no token present
  Powered by a `keva_connector_last_heartbeat` option that updates on
  every authenticated REST request.
* UX: "Disconnect from Keva" button clears the local token and stops
  Keva from authenticating future requests. (Keva-side will show the
  site as Error/Disconnected within a few minutes when the next
  scheduled heartbeat fails — clean break.)
* UX: confirmation dialogs on Regenerate Token + Disconnect so admins
  don't accidentally break a working connection.
* UX: scoped admin styling (Keva-coral header, status pulse, code
  formatting, collapsible diagnostics card) so the page feels like a
  product, not a stock WordPress options screen.
* UX: documentation + support links in the footer.

= 1.1.0 (2026-05-21) =
* Security: rate limiter now uses REMOTE_ADDR instead of trusting the
  spoofable X-Forwarded-For header (XFF can still be opted-in via
  KEVA_CONNECTOR_TRUST_FORWARDED_FOR for proxy deployments).
* Security: HTTPS enforcement no longer depends on the request Host
  header (which is attacker-controlled). Only the server-defined
  WP_ENVIRONMENT_TYPE constant can disable HTTPS now.
* Security: post_status on create/update is allowlisted to publish,
  draft, pending, private — preventing a leaked token from scheduling
  content via the `future` status or trashing content.
* Security: optional IP allowlist via KEVA_CONNECTOR_ALLOWED_IPS
  (exact IP or CIDR, IPv4).
* Rate-limited requests now return HTTP 429 with a clear message
  instead of generic 401 "invalid token".
* Auth callback returns WP_Error objects with explicit reason codes
  (no_token, invalid_token, ip_not_allowed, rate_limit_exceeded) so
  the Keva dashboard can surface the actual failure cause.
* Compatibility: end-to-end tested against WordPress 7.0-RC4 on PHP 8.4
  (closest stable to WP 7.0 GA via official Docker image at release
  time). 9/9 regression tests pass: all auth scenarios, post_status
  allowlist, list/create posts, Bearer auth variant. Min WP bumped to
  6.0 (5.9 EOL).

= 1.0.0 =
* Initial release
* Token-based authentication
* HTTPS enforcement
* Rate limiting
* Content CRUD (posts/pages)
* ACF field support
* Heartbeat health endpoint
* Admin settings page
