=== Kontinua ===
Contributors: hostspa
Tags: security, admin, tools
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 0.7.9
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connects a site to the Host.it Kontinua console. Host.it reads files and tables for a backup and can write them back. During a backup the site may stream packets to the Host.it ingest over HTTPS.

== Description ==

Kontinua is a WordPress plugin by **Host S.p.A.** (Host.it). It identifies the current site and, if you choose, helps you register it in the Host.it console.

= What this plugin does =

After activation, open **Settings → Kontinua**. You can:

* See a stable **site ID** created on this installation.
* Review a **site passport**: home URL, site URL, paths, table prefix, WordPress/PHP/MySQL versions, plus the active theme and active plugins (also included in the JSON download).
* Review a **readiness checklist** (whether `wp-config.php` and `ABSPATH` are readable, the database connection works, and the uploads directory is writable). These checks are informational only.
* **Download the passport as JSON.** The file does not include database passwords or file contents.
* Optionally **generate a pairing code** (stored on this site, valid 15 minutes) or connect with an agency API key (claim code valid up to 1 hour). After Host.it accepts pairing, the console can request the site inventory and open wp-admin as the administrator you chose. Each admin entry is listed on this screen. Automatic admin entry is refused when two-factor authentication is detected for that user (official Two Factor plugin, WP 2FA helpers, or filters `kontinua_user_has_two_factor` / `kontinua_allow_auto_login`).

Installing or activating the plugin does **not** contact Host.it. The signing key is kept by Host.it. This site stores only the public key. Signed routes and pairing require HTTPS (local demos may set `KONTINUA_ALLOW_HTTP`).

= What this plugin does not do =

This plugin does **not** keep a long-lived copy of the backup on the site. When the site is paired, Host.it can request file slices and table rows over a signed call, or ask a short-lived on-site runtime to stream packets to the Host.it ingest host allowlist. Database passwords never leave the site in REST responses. Restore writes require an explicit restore session. Pairing still starts only after you act in the console (or submit an API key claim).

= Third-party service (Host.it) =

Optional registration uses [Host.it](https://www.host.it/). Choose the console environment under Settings → Kontinua (default while beta: staging `https://app-staging.kontinua.host.it`). Override with `KONTINUA_CLOUD_URL` in wp-config.php if needed.

* **When:** only after an administrator generates a pairing code / API key claim, or when a paired site answers signed backup/restore calls.
* **What:** site identity (UUID, URLs, paths, versions); after pairing, administrator logins/roles for auto-login choice; during backup, file bytes and table dumps for the site prefix; never the database password in the passport or session JSON.
* **Service:** [https://www.host.it/](https://www.host.it/)
* **Terms:** [https://www.host.it/](https://www.host.it/)
* **Privacy:** [https://www.host.it/](https://www.host.it/)

== Installation ==

1. Upload the `kontinua` folder to `/wp-content/plugins/` or install the zip via Plugins → Add New → Upload Plugin.
2. Activate Kontinua.
3. Go to Settings → Kontinua.
4. Review the identity and readiness tables. Download the site passport JSON if you need it.
5. Optional: generate a pairing code and paste it in the Host.it Kontinua console.

== Frequently Asked Questions ==

= Does this plugin back up or restore my site? =

It does not keep a long-lived backup on the site. After you pair the site, Host.it can pull file/table data or ask a short-lived runtime to stream packets to Host.it ingest, and can write them back during a restore session. Pairing starts only when you act in the Host.it console (code or API key).

= Does it send data when I activate it? =

No. There is no outbound HTTP on activation. Generating a pairing code stores the code locally. An API-key claim posts identity/passport to the control plane you configured. Host.it receives backup bytes only while a paired backup runs.

= Where is the pairing code used? =

In the Host.it Kontinua console (Host.it account). Manual codes are not POSTed automatically; the API-key flow submits a claim to the control plane.

= Is the database password included in the passport or backup session? =

No. The password stays on the site (used only by the local backup runtime).

== Changelog ==

= 0.7.9 =

* Fix: backup DB stream opens `START TRANSACTION WITH CONSISTENT SNAPSHOT` when the engine allows it; SQL header `SET NAMES` follows the site DB charset; decimal/bit values stay quoted; PK resume no longer loops on key 0.
* Fix: file incremental `since` allows one hour of clock skew; hello reports site `unix` time.
* Fix: PHP error log normalizes messages before hashing, caps writes per hour, runs only when paired (filterable), and registers shutdown once.
* Fix: uninstall removes restore/php options, kontinua_* transients, harvester cron, uploads/kontinua-private, upgrade/kontinua-hold, and leftover collect runtimes.

= 0.7.8 =

* Security: /pair rate limit counts failed attempts only (higher per-IP plafond + soft global cap); optional `KONTINUA_TRUSTED_PROXIES` / filter `kontinua_trusted_proxies` for real client IP behind CDN.
* Security: signed-request anti-replay uses one sliding-window option instead of one transient per nonce.
* Security: unknown admin-entry tickets no longer flood the access log; entry URL uses admin-post.php (cache-bypass); filters for third-party 2FA.
* Security: backup runtime removes previous collect files on open, chmod 0600 when possible, hourly WP-Cron cleanup; idx/att under uploads/kontinua-private; fallback deploy path when ABSPATH is not writable.

= 0.7.7 =

* Feature: Settings → Kontinua console environment (staging / production when available). Default is staging so claims and backup push match the Host.it beta console; `KONTINUA_CLOUD_URL` still overrides.

= 0.7.6 =

* Fix: restore SQL splits statements with a quote-aware parser (semicolon inside strings no longer breaks the batch); table checks are anchored to DROP/CREATE/INSERT.
* Fix: legacy file index is NDJSON with a byte cursor (no full JSON decode per page); harvest index is built by streaming sorted walk without holding every path in RAM.
* Fix: table row counts use information_schema.TABLE_ROWS; fingerprints/rows without a usable PK use a stable ORDER BY; integer PK fingerprints use keyset pagination.
* Fix: plugin/theme update verify accepts version_compare equality with the offer or any version greater than the previous one (fewer false rollbacks). Update lists reuse WordPress transients instead of wiping them on every call.

= 0.7.5 =

* Fix: database backup no longer drops every column (column names are validated as identifiers, not as table names with the wp_ prefix).
* Fix: stop excluding zip/archives site-wide so digital product downloads and similar uploads are backed up; pull and harvest share one exclusion list.
* Fix: paths like foto..jpg are included; only real path segments "." / ".." are rejected.
* Fix: omitted files (oversized, excluded dirs, unreadable) are reported to the console; index paths with tabs/newlines are encoded safely.
* Fix: signed backup read allows wp-config.php and .htaccess (needed for a complete restore); kontinua-private stays out of the vault.

= 0.7.4 =

* Security: database credentials stay on the site (baked into the backup runtime); session open no longer returns the DB password.
* Security: backup runtime only pushes to allowlisted ingest hosts; table prefix is enforced; restore writes need an open restore session; plugin-private paths stay blocked (site config remains readable for signed backups).
* Security: HTTPS required on pairing and signed routes; pairing claim TTL 1 hour; /pair rate-limited; anti-replay uses per-nonce transients; file index stored under a private uploads path.
* Security: default control plane is production (`app.kontinua.host.it`); staging/demo must set `KONTINUA_CLOUD_URL`. Passport user list is administrators only, after pairing.
* Auto admin entry fires `wp_login` and refuses users with Two Factor enabled.

= 0.7.3 =

* Backup also covers WP_CONTENT_DIR when it lives outside ABSPATH (Bedrock / Composer layouts): plugins, themes, and uploads are included.
* Detached harvest runtime and signed pull share the same dual-root index (content paths use the wp-content/ prefix).

= 0.7.2 =

* Settings screen focuses on connection status and API key pairing; readiness, passport, and admin entry logs stay under Advanced tools.
* Plugins list shows a Settings link. Italian translations ship in the plugin package and follow the site language.

= 0.7.1 =

* Backup runtime protocol 3. Files up to 512 MB are included: large files travel in 4 MB parts inside the normal packets and a backup interrupted mid-file resumes from the last part, not from the start of the file.
* The time budget of each packet is capped by the host's PHP limit when the runtime cannot lift it; the console also learns, per site, when a reverse proxy cuts requests early and shortens its requests instead of failing the backup.

= 0.7.0 =

* Backup runtime protocol 2. Tables leave the site as one stream of compressed SQL segments (one connection, one ordered read per table) instead of hundreds of small pages. Unchanged tables are recognised from the engine's own metadata, so a backup of an idle site no longer scans the database.
* File index records the inode change time and prunes excluded folders before descending; unchanged files are decided from the index without touching them.

= 0.4.1 =

* PHP warnings are stored once at the end of the request. Silenced errors are ignored, and the same warning is not stored again for twelve hours.

= 0.4.0 =

* Recent PHP warnings and fatals stay on the site. Host.it can read that list with a signed call.
* The plugin still does not check whether the public site is up, and it still does not upload to storage.

= 0.3.1 =

* A later backup can skip a table whose contents match the previous one. The file list is scanned once per pass.
* Restore onto another server is performed by Host.it. This plugin still does not upload to storage.

= 0.3.0 =

* Host.it can read files and database tables to store a backup, and write them back on restore.
* The plugin still does not upload to object storage. The signing key stays on Host.it.

= 0.2.0 =

* The console can list and apply plugin, theme, and core updates.
* A plugin or theme folder is copied aside for that update and restored if the new version does not land.
* Core updates require a separate confirmation and are not rolled back automatically.

= 0.1.0 =

* Pairing code is completed by the console. The site stores a public key only.
* Signed on-demand site inventory.
* One-time wp-admin entry for the user chosen at pairing, written to a local log.
* Replaces the 1.0.0 local-only “marked as linked” flag.

= 1.0.0 =

* Initial site identity, passport JSON, and a local pairing code.

== Upgrade Notice ==

= 0.2.0 =

Updates run from the Host.it console. Only the updated plugin or theme folder is copied aside.

= 0.1.0 =

The console now completes pairing. A local “linked” flag is no longer enough.
