Skip to content

Sync with core trunk through r64690, require WP 6.8, and fix the trunk CI legs - #12

Merged
ericmann merged 7 commits into
mainfrom
core-sync
Oct 26, 2026
Merged

ericmann merged 7 commits into
mainfrom
core-sync

Conversation

@ericmann

@ericmann ericmann commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Brings core trunk's Secrets API changes since r64337 into the plugin. src/ and the shared test helpers now match trunk byte for byte. It also gets the trunk CI legs passing: they had been fataling since the API landed in core.

Core changesets ported

Changeset What Plugin commit
r64344 str_contains() / str_starts_with() in Site Health and list_secrets() 45b9f99
r64345 Same, in Mock_Keyring and Mock_Store 45b9f99
r64674 An unchanged write keeps the previous version (#66353) 6c3b46f
r64675 ?? in Mock_Store::get() (test-only; found in the parity check) 25674ea
r64690 array_all() in the config keyring (found in the parity check) 32e8972

WordPress 6.8 is now the minimum

r64690 uses array_all(), which core polyfills only from 6.8 (r59783). On 6.6 or 6.7 the default keyring would fatal. Rather than carry a polyfill of our own, the plugin now requires 6.8: the header, the README, and the scope page are updated. The old floor was never tested, since CI ran only latest and trunk. A PHP 7.4 / WP 6.8 leg now covers the new one.

Trunk: the plugin stands down, and the suite runs

  • Test bootstrap (d6ac91b). Core's test bootstrap has loaded its own Secrets API test helpers since r64337. Every trunk job fataled on Cannot declare trait WP_Secrets_Assertions. The plugin's copies now load only when the test library has none. With that fixed, every core-bound test passes on trunk against core's own implementation.
  • Plugin-only tests skip on a core that ships the API. The WP-CLI commands, migrator, legacy reader, and prototype fallback store don't load once the plugin stands down, so their five test classes skip there. The skip keys on core's wp-includes/secrets.php declaring wp_get_secret(), not on a missing plugin class. A plugin that failed to load its layer on 6.8 still fails.
  • Version gate (e0605db). version_compare() ranks 7.2-beta1-64606-src below 7.2. On a 7.2 beta, RC, or trunk build, the bootstrap therefore showed the error notice ("another plugin has already declared wp_get_secret()") instead of the superseded one. It now compares the release part only. Two new no-op gate tests cover pre-releases.

Follow-up, not in this PR: on 7.2 the plugin should keep offering the WP-CLI commands, running on core's classes instead of its own. Today it goes fully dark, which is enough to make this PR clean.

Beyond the straight ports

  • Example providers (36b7d59). The conformance test from r64674 fails both the AWS Secrets Manager and Vault examples. Vault adds version N+1 on every write, and PutSecretValue moves AWSPREVIOUS onto the unchanged value. Both now read the current value and skip an unchanged write. Vault still records a newly raised rotation flag, as a metadata-only write that fires the hook. A failed read never counts as "unchanged". There are three new Vault unit tests. The conformance test fails on the old examples and passes on the new ones.
  • PHPStan. The plugin analyzes at PHP 7.4, and the WordPress stubs leave out compat.php. tests/phpstan/compat-stubs.php declares the three polyfills src/ now uses, with compat.php's signatures. r64674 also trips one level-10 offsetAccess.nonOffsetAccessible, because PHPStan doesn't narrow $existing through $is_unchanged. That one line is ignored in phpstan.neon.dist rather than rewritten, to keep src/ identical to core. A core follow-up could guard the check with $has_current &&.
  • Docs. The versioning, rotation, extension-points, and scope spec pages, plus examples/README.md, are updated. docs/reference/classes.md is regenerated.

Testing

WordPress PHP Single site Multisite
latest (7.1.3) 7.4 503 pass, 30 skipped 503 pass, 19 skipped
6.8.8 7.4 503 pass, 30 skipped 503 pass, 19 skipped
trunk (7.2-beta1) 8.5 503 pass, 124 skipped 503 pass, 114 skipped
  • On 6.8 and latest the skip counts match main, so the new skip hides nothing there. On trunk the extra skips are the five plugin-only classes.
  • make lint compat analyse reference-check all pass.
  • Examples suite against Moto and Vault, single site and multisite: all of the new tests pass. Three tests fail locally only, the same on main, because .wp-env.override.json defines live AWS constants.

Props for the changelog

Ready for the next release's changelog page:

  • r64344, r64345: soean
  • r64674: ravipatel, ericmann, whyisjake
  • r64675: Soean, huzaifaalmesbah
  • r64690: soean

All committed by whyisjake.

Ports r64344 and r64345 from core trunk. The Site Health key source
checks, WP_Secrets_Libsodium_Provider::list_secrets(), Mock_Keyring and
Mock_Store compare with str_contains() and str_starts_with() instead of
strpos(). Core polyfills both since 5.9, below the plugin's 6.6 minimum.

PHPStan analyzes at PHP 7.4 and the WordPress stubs leave out
compat.php, so tests/phpstan/compat-stubs.php declares the two
polyfills with compat.php's signatures.

Props soean.
See Trac #66187.
Ports r64674 from core trunk. Saving a secret's current value again
demoted it to the previous slot, and settings forms do that on every
submit, so a rotation in progress lost the previous value it depends on.

WP_Secrets_Libsodium_Provider::set() now treats an unchanged write as a
no-op: nothing is stored and wp_secret_changed does not fire. A write
that raises needs_rotation on an unflagged value, such as
wp_import_option_as_secret() on an option holding the current value, is
still recorded, and keeps the previous version.

WP_Secrets_Provider::set() documents the rule for every provider, and
WP_Secrets_Provider_Conformance tests it. The versioning, rotation and
extension-point pages describe it.

PHPStan at level 10 loses the narrowing of $existing behind
$is_unchanged; the one line is ignored in phpstan.neon.dist so src/
stays as core committed it.

Props ravipatel, ericmann, whyisjake.
See Trac #66353, #66187.
The conformance test added with r64674 fails both example providers.
Vault's KV v2 engine adds version N+1 for any write, and PutSecretValue
moves AWSPREVIOUS onto the value AWSCURRENT already holds, so
re-saving the current value pushed the real previous one out.

Both now read the current value first and skip a write that would not
change it. Vault_KV2_Provider still records a raised rotation flag on
an unchanged value, as a metadata write with no new version, and
reports it. A failed read does not count as unchanged: the write goes
ahead and reports its own error.
Ports the Secrets API part of r64675 from core trunk. Test-only, with no
change in behavior: a stored record is always an array, never null.

Props Soean, huzaifaalmesbah.
Ports r64690 from core trunk: are_usable_salt_values() checks both salt
values with array_all() instead of a foreach. Core polyfills array_all()
from 6.8 (r59783), so 6.6 and 6.7 would have fataled on the default
keyring. The plugin now requires 6.8, rather than carry a polyfill of
its own.

The floor was never tested: CI ran only latest and trunk. A PHP 7.4 /
WP 6.8 leg now covers it. tests/phpstan/compat-stubs.php declares
array_all() with compat.php's signature.

Props soean.
version_compare() ranks '7.2-beta1-64606-src' below '7.2', so on a 7.2
beta, RC, or trunk build that ships the API, the bootstrap took the
conflict branch. It still loaded nothing, but showed the error notice
saying another plugin had declared wp_get_secret(). The version test
now compares the release part only.
Core's test bootstrap has loaded its own copies of the Secrets API test
helpers since r64337, so every trunk job fataled redeclaring
WP_Secrets_Assertions. The plugin's copies now load only when the
WordPress test library has none.

With that fixed, the core-bound tests pass on trunk against core's own
implementation. The plugin-only layer (the WP-CLI commands, the
migrator, the legacy reader, and the prototype fallback store) does not
load once the plugin stands down, so those five test classes skip on a
WordPress whose wp-includes/secrets.php declares wp_get_secret(). The
skip keys on that, not on a missing class, so a plugin that failed to
load its layer on 6.8 still fails.
@ericmann ericmann changed the title Sync with core trunk: r64344, r64345, r64674, r64675 Sync with core trunk through r64690, require WP 6.8, and fix the trunk CI legs Oct 26, 2026
@ericmann
ericmann merged commit 3e5ab41 into main Oct 26, 2026
16 checks passed
@ericmann
ericmann deleted the core-sync branch October 26, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant