Skip to content

v0.2.0 — KMS and Vault examples, CLI smoke test, multisite root-key fix

Choose a tag to compare

@ericmann ericmann released this 25 Sep 18:51
· 37 commits to main since this release
v0.2.0
8e4d627

Released 2026-09-25. This is the last release before the Trac patch
(ADR 0008). The public API
has the same signatures as 0.1.0. Two changes under src/ go into the patch: the root-key cache
and the multisite fix below.

Added

  • examples/aws-kms-keyring/, the first real WP_Secrets_Keyring. It is a single-file SigV4
    drop-in that moves custody of the root key to AWS KMS. Verified against live KMS.

  • examples/vault-provider/, a HashiCorp Vault KV v2 provider. It caps each secret at two
    versions, and PREVIOUS is strictly the version before the current one, so retiring a version
    never brings back an older one
    (ADR 0010). Verified against
    Vault 2.1.1, including a sealed server, and against OpenBao 2.7.0.

  • wp secret rotate --from=config-previous|config re-wraps the root key under the active
    keyring. --from=config is how an existing site moves onto a KMS keyring.

  • WP_Secrets_Keyring_Conformance, the keyring counterpart of the provider conformance suite.

  • make test-examples and an examples CI job. They run the three examples against Moto and
    a Vault dev server, on single site and multisite, including an automated conformance run for
    the AWS Secrets Manager example.

  • make smoke, a WP-CLI smoke test that drives a real, pinned wp binary against a
    throwaway install. It checks:

    • every subcommand and flag
    • the 0/1/2 exit-code contract
    • site-key rotation from end to end
    • drop-in loading through the real loader
    • a pass after converting to multisite

    It is part of make ci, and it runs in a smoke CI job on PHP 7.4 and 8.3.

Changed

  • WP_Secrets_Key_Manager keeps the unwrapped root key for the rest of the request, tied to the
    stored wrapped value. With a remote keyring, that means one call per request instead of one per
    secret. A rotation or re-wrap replaces the cached key, and an unwrap error is never cached
    (ADR 0009).
  • The WP_Secrets_Keyring::wrap() docblock now requires wrap() to be non-deterministic.
    rotate_site_key() already relied on it.
  • Breaking for anyone using the AWS Secrets Manager example: site-scope secrets now live at
    wp/site/<blog_id>/<name> instead of wp/<name>. See the example's README for the upgrade.

Fixed

  • Converting a single site to multisite made every secret unreadable. The wrapped root key
    stayed in wp_options while reads moved to wp_sitemeta, so the first read after conversion
    generated a new root key. The key manager now moves the key across instead.
  • The AWS Secrets Manager example shared one AWS secret across every site on a network.
  • The AWS Secrets Manager example reported has_previous as false for every secret, and for a
    minute or two after a delete it reported the secret as unreachable instead of absent.
  • make smoke failed on a host without wp-env, because WP-CLI ran out of memory at PHP's default
    128M limit.
  • The recorded cause of the old --version=previous bug was wrong. It was wp-env's argument
    parser, not WP-CLI.

Security

  • The docs site's sharp dependency was raised to 0.35.4, for libvips and libheif advisories.
    The plugin itself was not affected.

Documentation

Full documentation: https://secrets-api-docs.view.fast/ · Changelog: https://secrets-api-docs.view.fast/changelog/0-2-0/