=== NEWTIV Migrate ===
Contributors: newtiv
Tags: export, migration, users, headless, password
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Export your users (with their password hashes) and your content to one encrypted file, to move them into a new application without losing anyone.

== Description ==

You are building a new web or mobile application and want to keep the people who already have an account on your WordPress site. NEWTIV Migrate exports, in one file:

* **users**: username, email, name, registration date, roles, and optionally their **password hashes**, profile fields, WooCommerce addresses and any other user meta you name;
* **content**: posts, pages, products and custom post types, with categories, tags, custom fields and author;
* **comments** (without IP addresses) and the **media library** list with file addresses.

Because the password hashes are included, your application can check a user's usual password exactly like WordPress does (phpass for older accounts, bcrypt for WordPress 6.8 and later), then store it in its own format at the first sign-in. Nobody has to reset their password.

**Security first**

* The file is always encrypted with a passphrase you choose: key derived with Argon2id, content encrypted with XChaCha20-Poly1305 (libsodium secretstream). Without the passphrase the file cannot be read.
* The file is streamed to your browser and never stored on the server.
* Only administrators can export, and they must type their account password again. Five wrong passwords lock the export for 15 minutes.
* The last 20 exports are listed: who, when, how many records, with or without password hashes.
* Password hashes are optional: untick them for a content-only export.

**Large sites**: users and content are read in batches of 200. From the command line: `wp newtiv-migrate export site.ntvm` (see `wp help newtiv-migrate export`).

This plugin does not connect to any external service.

== File format ==

1. First line: `NTVMIG1`.
2. Second line: a JSON header with the key derivation parameters (`kdf.alg` = argon2id13, `kdf.opslimit`, `kdf.memlimit`, `kdf.salt` in base64) and the secretstream header (`header`, base64).
3. Then frames: a 4-byte big-endian length followed by the ciphertext of one secretstream message. The last frame has the FINAL tag; a file without it is incomplete.

Key: `crypto_pwhash(32, passphrase, salt, opslimit, memlimit, ARGON2ID13)`. Decrypted, the frames form NDJSON, one record per line, each with a `type`: `meta`, `user`, `term`, `post`, `media`, `comment`, then `end` with the counts, to check that nothing is missing.

Any libsodium binding can read it: PyNaCl (Python), libsodium-wrappers (Node.js), ext-sodium (PHP).

User records carry `pass` and `pass_format` (`wp-bcrypt`, `phpass`, `bcrypt`, `md5`, `argon2`). Meta values are exported exactly as stored in WordPress (arrays stay PHP-serialized).

== Installation ==

1. Upload the plugin and activate it.
2. Go to **Tools → NEWTIV Migrate**.
3. Choose what to export, choose a passphrase (or generate one), type your password, download.
4. Keep the passphrase somewhere safe, separately from the file.

== Frequently Asked Questions ==

= Can someone use the file to sign in to my site? =

No. A password hash cannot be used to sign in; it can only be used to check a password someone types. And the file itself cannot be read without the passphrase.

= I lost the passphrase. =

The file cannot be opened. Make a new export.

= My host says the sodium extension is missing. =

The plugin needs PHP's sodium extension (included with PHP since 7.2, enabled by almost every host). Without it, the export button stays disabled.

== Changelog ==

= 1.0.0 =
* First release: encrypted export of users (with password hashes), content, comments and media list; WP-CLI command; export log.
