diff --git a/SECURITY.md b/SECURITY.md index 575d97b..7bab642 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -25,9 +25,9 @@ explanation rather than silence. ## Scope -This is a pre-release feature plugin (`0.3.0`) tracking a proposal, not yet shipped in WordPress -core. There is no supported-version matrix yet: `main` is the only supported branch, and fixes -land there. +This is a pre-release feature plugin (`0.4.0`). The API is in WordPress core trunk for 7.2, and +`src/` follows it. There is no supported-version matrix yet: `main` is the only supported branch, +and fixes land there. Things worth reporting: diff --git a/docs/changelog/0-4-0.md b/docs/changelog/0-4-0.md new file mode 100644 index 0000000..ee5aa63 --- /dev/null +++ b/docs/changelog/0-4-0.md @@ -0,0 +1,82 @@ +--- +title: "0.4.0" +description: "The first release since the Secrets API landed in core as r64337: src/ now follows core trunk, WordPress 6.8 is the minimum, the WP-CLI commands keep working on 7.2, and WP_SECRETS_KEY is about to become required." +date: 2026-10-30 +--- + +# 0.4.0 + +Released 2026-10-30. The Secrets API landed in WordPress core trunk for 7.2 as +[r64337](https://core.trac.wordpress.org/changeset/64337) ([#66187](https://core.trac.wordpress.org/ticket/66187)). +Since then the sync runs the other way: core trunk is the source, and the plugin ports each core +changeset into `src/`. In this release `src/` and the shared test helpers match trunk as of +[r64995](https://core.trac.wordpress.org/changeset/64995), byte for byte. + +## Ported from core + +| Changeset | Change | Props | +|---|---|---| +| [r64344](https://core.trac.wordpress.org/changeset/64344), [r64345](https://core.trac.wordpress.org/changeset/64345) | `str_contains()` and `str_starts_with()` in Site Health, `list_secrets()` and the test mocks. | Soean | +| [r64674](https://core.trac.wordpress.org/changeset/64674) | Saving a secret's current value again keeps the previous version, and fires no `wp_secret_changed`. The provider conformance suite tests it. [#66353](https://core.trac.wordpress.org/ticket/66353) | ravipatel, ericmann, whyisjake | +| [r64675](https://core.trac.wordpress.org/changeset/64675) | `??` in `Mock_Store::get()`. | Soean, huzaifaalmesbah | +| [r64690](https://core.trac.wordpress.org/changeset/64690) | `array_all()` in the default keyring. | Soean | +| [r64995](https://core.trac.wordpress.org/changeset/64995) | `??` instead of the remaining fallback ternaries. | Soean, westonruter, mukesh27 | + +whyisjake committed r64337 through r64690, and SergeyBiryukov committed r64995. + +## Changed + +- **WordPress 6.8 is the minimum.** r64690 uses `array_all()`, which core polyfills only from 6.8. + CI has a PHP 7.4 / WordPress 6.8 leg. +- **The WP-CLI commands keep working on a WordPress that ships the API.** Core left `wp secret` and + `wp network-secret` out. On 7.2 the plugin now registers them on core's implementation and loads + nothing else. `migrate-legacy` exits with an explanation there instead. See + [ADR 0014](../decisions/0014-the-plugin-keeps-wp-cli-on-a-core-that-ships-the-api.md). +- **The AWS Secrets Manager and Vault examples skip an unchanged write,** so they pass the + conformance test from r64674. + +## Fixed + +- On a 7.2 beta, RC or trunk build, the plugin showed the "another plugin has already declared + `wp_get_secret()`" error instead of standing down, because `version_compare()` ranks + `7.2-beta1` below `7.2`. Only the release part of the version is compared now. +- The test suite runs against a WordPress that ships the API. Every trunk job had failed on a + duplicate test helper since r64337. + +## Coming in core: `WP_SECRETS_KEY` becomes required + +This release, like core trunk today, still derives the key from `LOGGED_IN_KEY` and +`LOGGED_IN_SALT` when `WP_SECRETS_KEY` is not defined. That is about to change. Rotating the salts +locks every secret on such a site ([#66187 comment:24](https://core.trac.wordpress.org/ticket/66187#comment:24)). +The salts were also read without the checks `wp_salt()` applies +([comment:27](https://core.trac.wordpress.org/ticket/66187#comment:27)). The decision is +[ADR 0016](../decisions/0016-require-wp-secrets-key.md), which supersedes +[ADR 0015](../decisions/0015-keep-the-salt-fallback-and-generate-a-key-at-install.md). The plugin +ports the change once core commits it. + +Define `WP_SECRETS_KEY` now. On a site that already stores secrets under the fallback, move them +first, or they become unreadable: + +1. Set `WP_SECRETS_KEY` to a new value, from `wp secret generate-key`. +2. Set `WP_SECRETS_KEY_PREVIOUS` to the old `LOGGED_IN_KEY . LOGGED_IN_SALT`, the two values + joined together. +3. Run `wp secret rotate`. +4. Remove `WP_SECRETS_KEY_PREVIOUS`. + +## In review in core + +Each of these will be ported once committed. + +| Ticket | Change | PR | +|---|---|---| +| [#66187](https://core.trac.wordpress.org/ticket/66187) | Require `WP_SECRETS_KEY`. Reject the placeholder and any key equal to a key or salt. | [15258](https://github.com/WordPress/wordpress-develop/pull/15258) | +| [#66399](https://core.trac.wordpress.org/ticket/66399) | `setup-config.php` writes `WP_SECRETS_KEY`, and `wp-config-sample.php` has a placeholder for it. | [15124](https://github.com/WordPress/wordpress-develop/pull/15124) | +| [#66380](https://core.trac.wordpress.org/ticket/66380) | Site Health reports a broken backend, and stops giving advice that locks stored secrets. `secrets.php` is listed as a drop-in. | [15263](https://github.com/WordPress/wordpress-develop/pull/15263), [14848](https://github.com/WordPress/wordpress-develop/pull/14848) | +| [#66413](https://core.trac.wordpress.org/ticket/66413) | A failed read of the root key no longer replaces it. | [15186](https://github.com/WordPress/wordpress-develop/pull/15186) | +| [#66414](https://core.trac.wordpress.org/ticket/66414) | Secret names cannot end in a newline, values stay out of stack traces, and All Settings no longer lets the root key be edited. | [15200](https://github.com/WordPress/wordpress-develop/pull/15200) | +| [#66424](https://core.trac.wordpress.org/ticket/66424) | A failed read of a secret's record no longer reads as a missing secret. | — | + +WP-CLI's `wp config create` will generate the key as well +([wp-cli/config-command#235](https://github.com/wp-cli/config-command/pull/235)). Moving the +`wp secret` commands into WP-CLI is proposed in +[wp-cli/entity-command#677](https://github.com/wp-cli/entity-command/issues/677). diff --git a/docs/spec/scope.md b/docs/spec/scope.md index 3839a14..a420d78 100644 --- a/docs/spec/scope.md +++ b/docs/spec/scope.md @@ -15,7 +15,7 @@ scope", and "Timeline" in the [proposal][proposal]. ## As built -**The plugin.** `secrets-api.php` declares version `0.3.0`, `Requires at least: 6.8`, and +**The plugin.** `secrets-api.php` declares version `0.4.0`, `Requires at least: 6.8`, and `Requires PHP: 7.4`. **Core-bound versus plugin-only.** Everything under `src/` is written to be copied into diff --git a/secrets-api.php b/secrets-api.php index b973f99..708e7b8 100644 --- a/secrets-api.php +++ b/secrets-api.php @@ -3,7 +3,7 @@ * Plugin Name: Secrets API * Plugin URI: https://github.com/ericmann/secrets-api * Description: Feature plugin for the WordPress Secrets API proposed for 7.2. Encrypted, versioned credential storage with pluggable storage and keyring back ends. - * Version: 0.3.0 + * Version: 0.4.0 * Requires at least: 6.8 * Requires PHP: 7.4 * License: GPL-2.0-or-later @@ -25,7 +25,7 @@ /** * Plugin version. */ -define( 'WP_SECRETS_API_PLUGIN_VERSION', '0.3.0' ); +define( 'WP_SECRETS_API_PLUGIN_VERSION', '0.4.0' ); /** * The WordPress version expected to ship the Secrets API in core.