Skip to content

Releases: IsuDevelopment/wp-content-bridge

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 03 Sep 22:20
bb710f2

Answers which redirect is missing, and stops a renamed page's old URL serving stale content.

Runtime verification: this release originally shipped without an inventory run, deliberately, and said so. The run has since been completed: 26/26 PHP verifiers and all three shell verifiers green on 2026-09-04 (commit 9c69b52). error-statistics-verification.php ran for the first time at any version and reached its measured branch against a live Redirection 5.9.0 404 log, rather than only its refusal branch.

The only code difference between this artifact and the verified commit is one whitespace character, so the artifact below is the verified build and there is no 0.10.1.

Changelog

  • New: get-404-statistics answers which redirect is missing, which creating a redirect cannot. It reports the paths that returned 404 and how often, read from the Redirection plugin's own log, behind the new off-by-default 404 statistics ability switch and the new wpcb_read_error_statistics capability.
  • Aggregate only, by construction. A result carries the requested path and a hit count and nothing else. Visitor IP, user agent, referrer, and request data are never read into the plugin, never stored, never returned, and never projected to an MCP client — and no parameter exists that could include them, so no retention or redaction obligation attaches to this plugin.
  • "Nothing collects this", "the log is switched off", "you may not read it", and "no 404s happened" are four different answers and stay four different answers. Yoast SEO Premium collects no 404 data at all, so a Yoast-only site reports the data as unavailable rather than reporting zero — which would read as a healthy site. A disabled log names the Redirection setting responsible. Every result also reports the retention window it covers, and says so explicitly when retention cut a requested range short, because pruned rows would otherwise look like 404s that stopped happening.
  • Reading statistics is deliberately not wpcb_manage_redirects. Redirection separates the two in its own permission model, so "diagnose the site without authority to change its routing" is a grant you can actually express. Because the log is read directly, Redirection's own permission for it still applies — by default that means Administrator, widened through Redirection's own filter if a site wants an integration principal to read it. Nothing here enables, prunes, or resets any log.
  • get-diagnostics now reports redirect providers, as redirects.enabled plus a redirects.providers list with a detected flag each — and it reports them whether or not the redirect abilities are switched on. Missing redirect abilities have two very different causes, the switch being off and no provider being installed, and they need opposite fixes. Diagnostics schema version moves to 1.2; the addition is backward-compatible.
  • update-permalink now invalidates the old URL's cache and reports what it did. A page-cache entry for the old URL is keyed by URL, so the post-scoped invalidation every write already performs cannot reach it, and it keeps serving the old page — the rename appears not to have taken effect. The write now notifies a bounded set, exactly the old and new URL, through public single-URL purge hooks and a new wp_content_bridge_purge_urls action for sites to bind. The result reports which channels were notified and flags delegated when the actual purge depends on site-level glue; it never claims a purge it cannot observe.
  • Fixed: wpcb_upload_media, added in 0.9.0, could not be granted through the settings screen and survived uninstall. It was missing from the capability list the screen renders and from the uninstall cleanup. Both now include it.
  • The database schema version moves to 14, so an active install grants the new capability only when the plugin is reactivated — until then the statistics ability refuses, which is the correct failure direction.
  • Adds tests/Integration/error-statistics-verification.php, a read-only runtime fixture for the statistics port. It writes no log row, changes no Redirection setting, and prunes nothing.

Install: download wp-content-bridge.zip below and install it as a plugin, or let the built-in updater offer it.

Full Changelog: v0.9.0...v0.10.0

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 03 Sep 22:16
244a58f

Media writes, permalinks, and the completed redirect lifecycle.

Action required if you chain writes: use the version_token a write returns, not the one you first read. The token now covers meta, the featured image, attachment edits and the slug, so a token taken before one write is correctly rejected by the next. Clients that already re-read are unaffected.

Published retroactively on 2026-09-03, minutes after v0.8.4, having been committed the same day.

Runtime verification: 25/25 verifiers green on WordPress 7.1 (2026-09-03). That run found three defects before release, all fixed in this tag - see the changelog.

Changelog

  • Action required if you chain writes: use the version_token a write returns, not the one you first read. The token was blind to most of what a write changes. It hashed only post_modified_gmt, the title, the content and the status, so an SEO write, a Custom or Service Schema write, a featured-image change, an attachment edit, and a slug change all left it byte-identical after succeeding. Two agents could read the same token, both write, and the second would silently overwrite the first with no conflict raised — the one thing the token exists to prevent. It now covers the post's meta and its other mutable columns. Nothing changes for a caller that already re-read before each write; a caller that reused a stale token was relying on a defect and now gets the 409 it should always have had.
  • post_modified_gmt could not have covered this on its own: it has one-second resolution, so a second edit inside the same second leaves it unchanged. That is why a slug change was accepted against a stale token, and it failed intermittently rather than always.
  • New: redirect abilitiessearch-redirects, create-redirect, update-redirect, delete-redirect, behind the off-by-default Redirect abilities switch and the wpcb_manage_redirects capability. They work through one provider-neutral port over Yoast SEO Premium's Redirect Manager and the Redirection plugin, requiring each provider's own native permission in addition to the bridge's.
  • Reads span every available provider and writes name their target explicitly; nothing is ever dual-written or silently substituted into a different engine. A site running both plugins has two live redirect engines serving the same paths, so every result names which provider holds a path, and collision, chain, and loop checks are cross-provider. Verified on a live site with both engines active.
  • Reserved paths are refused, including this plugin's own /llms.txt, and a redirect cannot shadow live content. That last check had a defect during development: a redirect on the site root / was accepted, because url_to_postid() answers 0 there. Fixed and covered by a regression test.
  • New: permalink changesupdate-permalink changes one post's slug and returns the previous URL beside the new one, so a redirect can be created from it. A slug already in use is refused, not quietly turned into slug-2 the way WordPress would; a slug that normalizes to nothing is refused rather than stored empty, which would make WordPress regenerate one from the title. It cannot change the site-wide permalink structure. Gated by a new per-type Change permalink policy.
  • New: media writesupdate-featured-image assigns or removes a featured image, create-media imports one image from a remote URL, and update-media edits an existing attachment's title, alternative text, caption, and description. Each is behind its own off-by-default switch: assigning an image the site already holds, importing a file from the internet, and editing text about a file are separate grants.
  • create-media requires the new wpcb_upload_media capability plus native upload_files, and is deliberately not covered by wpcb_edit_content: a principal that may edit text is not thereby one that may put files on the server. The URL is screened by WordPress's own host allowlist, which refuses loopback, private, link-local and cloud-metadata addresses and re-checks every redirect target. The stored file type is decided by the downloaded bytes, not the URL or its extension, and only JPEG, PNG, GIF, WebP and AVIF are accepted — never SVG. An idempotency_key is required so a retried call returns the same attachment instead of importing a second copy. It creates the attachment only; it never attaches it to a post.
  • update-featured-image refuses any attachment that is not an image or that the caller cannot read. WordPress itself accepts any attachment ID as a thumbnail — a PDF, or a private upload — and themes then render it in a public image slot.
  • Fixed: search-content results had no stable order. Sorting by date, modification time, or title used no tie-break, so rows sharing that value came back in whatever order the database chose. Two posts with the same modification time is what every bulk import produces. On a single read that was untidy; on a paginated read it was a correctness bug, because a row could appear on two pages or on none. Results are now ordered deterministically. search-content, get-editorial-context, and llms.txt source selection all read through the same path and are all fixed.
  • Fixed: get-url-seo reported "rendered schema unavailable" without saying why. The reader answered five different failures — a refused request, a non-200 response, an oversize page, a cross-origin URL, and a page that genuinely emits no JSON-LD — with the same empty result. A blocked loopback request is a host fault to fix; a page with no JSON-LD is a correct answer, and self-requests are exactly what a firewall or edge proxy blocks. The warning now names the cause.
  • get-custom-schema now returns the post it describes: title, slug, permalink, status, publication and modification dates, and featured-image identity. These are the fields a JSON-LD document is built from, and their absence meant authoring a schema for one page needed a separate content read. Measured at 14 ms and under a kilobyte for the whole response.
  • get-media-by-id now returns a version_token. It is the only read that issues one for an attachment, so without it update-media would have had no token to submit.
  • validation.context_resolved on the Custom Schema abilities is documented as always false and not a failure signal — it reports that validation is source-level only, and it can accompany valid: true.
  • Three new off-by-default options (Redirect abilities, Media writes, Import images from a URL), one new capability (wpcb_upload_media), and two new per-type policies (Set featured image, Change permalink). The database schema version moves to 13, and an active install grants the new capability only when the plugin is reactivated — until then abilities requiring it refuse, which is the correct failure direction.
  • Adds tests/Integration/ability-timing-probe.php, a read-only diagnostic that times each read ability in-process so a slow transport can be told apart from slow PHP. It asserts nothing and changes nothing, so it is safe to run on a production install.

Install: download wp-content-bridge.zip below and install it as a plugin, or let the built-in updater offer it.

Full Changelog: v0.8.4...v0.9.0

v0.8.4

Choose a tag to compare

@github-actions github-actions released this 03 Sep 22:15
4fef9dd

WordPress 7.1 Abilities API adoption. Minimum WordPress is now 7.1 and minimum PHP 8.2.

Two changes are visible to existing clients and both are listed below: domain rejections now answer 4xx instead of the HTTP 500 every one of them used to return (public error codes unchanged), and update-llms-txt is now annotated destructive.

Published retroactively on 2026-09-03. The release was committed on 2026-09-01 and tagged two days later, so this tag's date is later than the work it contains.

Runtime verification: 24/24 verifiers green on WordPress 7.1 (2026-09-01).

Changelog

  • WordPress 7.1 is now the minimum supported version (ADR 0027). The plugin declares it and contains no 6.x compatibility branches. Nothing here is optional on an older release — the exposure flag, the lifecycle hooks, and the filtering used below all arrived in 7.1.
  • Fixed: every rejection answered HTTP 500. No ability error carried a status, so a missing post, a refused capability, and an oversized payload were all indistinguishable from a server fault over REST — agent clients retried them and monitoring read them as outages. Domain rejections now answer the status they always meant: 400 for invalid input, 403 for a refused capability, 404 for content that is missing or not visible to the caller, 409 for a concurrency or state conflict, 413 for an over-limit payload, 501 for an unavailable provider, and 500 only for an actual internal fault. Public error codes are unchanged, so any client matching on code keeps working; only the status differs.
  • Missing and not-visible deliberately share 404. Which of the two it was is not disclosed, so status codes cannot be used to enumerate content a caller may not read.
  • wp-content-bridge/update-llms-txt is now annotated destructive (ADR 0028), because its input is a complete configuration that replaces the stored one — a caller omitting a field loses it. Its HTTP method is unchanged: it remains non-idempotent, so it is still POST, not DELETE. No other annotation changed; the other thirty were already correct under the definition this release finally writes down.
  • Abilities now declare 7.1's unified public exposure flag alongside the explicit show_in_rest they already carried. Registration metadata is built in one place, which removed thirteen near-identical per-class helpers — two of which took different single booleans under the same name.
  • Added an off-by-default invocation telemetry diagnostic mode (ADR 0029). Enabled, it records the last 200 invocation attempts — ability name, principal, channel, outcome, timestamp, and nothing else — including the permission denials that previously left no trace anywhere. It never touches the audit table, never stores ability input, and writes once per request. It is a diagnostic, not an audit record: the hook fires before validation and authorization, so an entry proves an attempt was made, never that anything happened.
  • get-diagnostics reports the site's minimum WordPress version and which Abilities API features it actually detected at runtime, rather than assuming them from a version number.

Install: download wp-content-bridge.zip below and install it as a plugin, or let the built-in updater offer it.

Full Changelog: v0.8.3...v0.8.4

v0.8.3

Choose a tag to compare

@github-actions github-actions released this 14 Aug 08:52
f0d3857

Full Changelog: v0.8.2...v0.8.3

v0.8.2

Choose a tag to compare

@github-actions github-actions released this 12 Aug 06:56
29e78a2

Full Changelog: v0.8.1...v0.8.2

v0.8.1

Choose a tag to compare

@github-actions github-actions released this 11 Aug 19:27
fed1ab5

Full Changelog: v0.8.0...v0.8.1

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 11 Aug 08:53
c159cae

Full Changelog: v0.7.1...v0.8.0

v0.7.1

Choose a tag to compare

@github-actions github-actions released this 09 Aug 18:10
d9e104e

Full Changelog: v0.7.0...v0.7.1

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 09 Aug 14:12
1af3ef6

Full Changelog: v0.6.0...v0.7.0

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 09 Aug 09:31
573f646

Full Changelog: v0.5.0...v0.6.0