Skip to content

Releases: CrawlCove/wordpress-seo-connector

Crawl Cove Connector 0.10.8

Choose a tag to compare

@github-actions github-actions released this 22 Oct 13:01
  • Fix: pushing a title or description no longer strips embeds from the
    post.
    After every write the plugin re-saved the whole post to refresh
    caches, and WordPress re-filtered the body as the pushing user. For a user
    without the unfiltered_html capability (any Author, and every site
    administrator on multisite) that deleted iframes, scripts and forms an
    admin had put in the content. The plugin now writes SEO meta only and
    purges caches directly (clean_post_cache(), W3 Total Cache, LiteSpeed
    Cache, WP Fastest Cache). Yoast still rebuilds its indexable from its own
    meta watcher. The post's modified date no longer changes on a push. New
    ccc_after_post_write action.
  • Fix: Revert no longer refuses a change that cleared a value. 0.10.7's
    check compared the field with the pushed text, but a cleared value can read
    back as a fallback (an empty Polylang French homepage title reads as the
    English one), so Revert reported a newer value that did not exist. It now
    compares with what the SEO plugin served right after the push, recorded
    as after in the change log entry when it differs from to.
  • Docs: the wordpress.org copy installs from the directory. bin/build-zip.sh --wporg now also rewrites readme.txt Installation step 1 to "Plugins → Add
    Plugin, search for Crawl Cove Connector", so the listing never sends a
    directory user to the GitHub zip. The GitHub copy keeps the download step,
    and both readmes now use the current "Add Plugin" menu name.

Crawl Cove Connector 0.10.7

Choose a tag to compare

@github-actions github-actions released this 21 Oct 13:02
  • Fix: reverting an older change no longer wipes a newer one (review
    ticket #248). Revert wrote the old value back without looking, so undoing
    an earlier push after a re-push, or after a hand edit in the SEO plugin,
    silently overwrote the newer value. /revert now answers 409
    ccc_value_changed with the current value and writes nothing, unless sent
    force: true. The Tools page marks overwritten entries "replaced by a
    later change" and offers "Revert anyway" when a revert is refused.
  • Fix: pushed titles and descriptions keep their SEO template variables
    (review ticket #233). The value was run through core
    sanitize_text_field(), which deletes % plus two hex digits, so
    %category% was stored as tegory% and %%date%% as %te%%, then
    printed literally in the page title. Tags are still stripped. Verified on
    real Rank Math, Yoast, SEOPress and AIOSEO.

Crawl Cove Connector 0.10.6

Choose a tag to compare

@github-actions github-actions released this 18 Oct 13:00
  • Security: /resolve and /changes no longer disclose what the user
    cannot read
    (review ticket #227). A Contributor or Author could resolve
    ?p=N for any id and read the title and SEO values of other users'
    drafts and private posts, and of privacy requests (whose title is the
    requester's email). Those now answer ccc_unresolvable, like a missing
    post. /changes lists only entries on targets the user may edit;
    administrators still see the whole log. The app resolves only crawled
    public URLs, so nothing changes for it.
  • The Application Passwords hint (Tools page, readme FAQ) now tells users of
    other security plugins to look for a setting with a similar name, instead
    of asserting they all have one; matches the crawlcove.com FAQ (seo #222).

Crawl Cove Connector 0.10.5

Choose a tag to compare

@github-actions github-actions released this 17 Oct 13:00
  • When a plugin has switched Application Passwords off on an HTTPS site
    (Wordfence's default), the Tools page and the API 401 now say so and name
    Wordfence's setting, instead of blaming HTTPS and offering the proxy fix
    (review ticket #220). Same ccc_app_passwords_unavailable code; new FAQ.
  • readme.txt and README install step 4 say the desktop app can push one fix
    at a time or every open title and description finding at once (app 1.3.8
    bulk push, ticket #217). Docs only.
  • wordpress.org screenshot-1 regenerated with the Application Passwords row
    that 0.10.4 added to the Tools page; caption updated to match.

Crawl Cove Connector 0.10.4

Choose a tag to compare

@github-actions github-actions released this 14 Oct 13:01
  • The plugin now says when the site cannot accept Application Passwords at
    all
    (review ticket #211). WordPress core only enables them over HTTPS or
    with WP_ENVIRONMENT_TYPE=local, so on a plain-http staging site, or an
    HTTPS site behind a proxy that hides the scheme, core silently ignored the
    desktop app's login and the app could only report "wrong credentials".
    Every route now answers such an anonymous request with its own error,
    ccc_app_passwords_unavailable (401), whose message names the cause; the
    Tools page Status table gains an "Application Passwords" row (On, or Off
    with the proxy fix and the last-resort filter); readme.txt gains a "Does my
    site need HTTPS?" FAQ; README documents the code for the app. A logged-in
    admin's own cookie session is never blocked. New CCC_App_Passwords
    class, 5 unit tests, and tests/integration/app-passwords-checks.sh (12
    checks, wired into run.sh) which lifts the harness's own
    wp_is_application_passwords_available filter and proves both surfaces
    against real core auth.

  • Update URI header (review ticket #212). Installed from GitHub, the
    plugin had no Update URI, so core asked api.wordpress.org for updates
    against a slug nobody has claimed yet; whoever one day owns
    crawl-cove-connector there would have been offered to every GitHub
    install as an upgrade. The header now points at
    https://crawlcove.com/wordpress-plugin, which makes core skip the
    directory for this plugin. bin/build-zip.sh --wporg strips the line for
    the wordpress.org SVN copy (the directory serves updates only to plugins
    without one, and Plugin Check flags it); plugin-check.sh checks that
    copy. No update notices for GitHub installs yet: that needs an external
    request both readmes promise not to make.

  • README documents how to find the REST root. WordPress serves the API
    at /wp-json/, /index.php/wp-json/ or /index.php?rest_route=/
    depending on the permalink setting, and a client that hard-codes
    /wp-json/ cannot reach a plain-permalink site (the desktop app did
    exactly that, review ticket #200). The contract now says: read the
    Link rel="https://api.w.org/" header on the site URL, fall back to the
    ?rest_route= form, and treat a 2xx non-JSON body as "not the API". New
    harness script tests/integration/rest-root-checks.sh (13 checks, wired
    into run.sh) pins the header, the advertised root and the route under it
    against a real WordPress on both the plain (?rest_route=) and the pretty
    (/wp-json/) permalink setting, and the taxonomy script now also resolves
    a post and the static front page by their pretty URLs (what the crawler
    really sends), not only by ?p=N. No plugin code change.

  • No em dashes in what the plugin itself says. Six strings reworded:
    the plugin header description (the Plugins screen), the Tools page's
    "None" SEO-plugin line, and four REST error messages the desktop app
    shows (no SEO plugin, URL not on this site, static front page, Rank Math
    homepage title clear). The Polylang homepage label is now
    "Homepage (latest posts, fr)". Error codes are unchanged, so the app
    needs nothing. POT regenerated. A unit test tokenises the plugin's PHP
    and fails on an em dash in any string literal or inline HTML (comments
    exempt, the lone empty-cell placeholder allowed).

  • Readmes rewritten without em dashes, and a short wordpress.org
    changelog.
    readme.txt and README.md (including the repo's H1) now follow
    the house style, with the sentences reworded rather than the dashes
    swapped for hyphens. The readme.txt changelog is a few plain lines for
    0.10.x plus one summary of the GitHub-only versions, linking here for the
    full history (167 words, was 1,324). Unit tests keep both readmes free of
    em dashes outside code blocks and that changelog under 250 words.
    CHANGELOG.md got the same rewrite (61 em dashes, version headings now
    read ## 0.10.3 (2026-10-04); the build and release scripts still find
    them) and the same test, and so did SECURITY-NOTES.md (69).

  • Both readmes now say the desktop app is paid. The plugin is free, but
    the Crawl Cove crawler it works with is a paid app with a free trial, and
    neither readme said so: a reader saw "free, GPL" and found out at
    /pricing. One sentence in the Description (readme.txt) and "Why this
    plugin exists" (README.md), linking crawlcove.com/pricing. Plus an FAQ:
    deleting the plugin removes its change log, so revert history goes with
    it, while the applied titles and descriptions stay. A unit test pins
    both, and that the Stable tag matches the plugin version. No code change.

Crawl Cove Connector 0.10.3

Choose a tag to compare

@github-actions github-actions released this 05 Oct 13:02
  • Tools page shows whether the desktop app has connected. The readmes
    promised a "connection status" but the Status table only listed the
    detected SEO plugin and the endpoint, so a wrong password or URL typo
    looked like nothing at all. There is now a "Desktop app" row: "Not
    connected yet" until an authenticated user calls a crawlcove/v1 route,
    then "Last connected by ". Recorded in the permission
    callback, so rejected and anonymous requests never count; stored as one
    non-autoloaded option (ccc_last_connection), written at most once a
    minute per user, removed on uninstall. Inbound only: no external request.
    No REST contract change.

Crawl Cove Connector 0.10.2

Choose a tag to compare

@github-actions github-actions released this 03 Oct 13:02
  • Change log keeps 1,000 entries, and evicts reverted ones first. The
    log was capped at 200 entries and silently dropped the oldest when full.
    A title and a description on one post are two entries, so one push over
    100 posts overflowed it: the earliest changes of that same push were
    already gone — and unrevertable — when it finished, while both readmes
    promised "any change can be reverted". The cap is now 1,000 (worst case
    at the input limits is about 2MB in a non-autoloaded option that only
    /apply, /revert and the Tools page read), already-reverted entries are
    dropped before any live one, the cap is documented in both readmes, and
    the Tools page says when the log is full. No REST contract change: the
    /changes shape is unchanged, it can just return more entries. The
    Tools page paginates the log (100 rows a page, revert keeps your page)
    and loads each page's posts in one query, so the bigger cap costs the
    admin nothing.

Crawl Cove Connector 0.10.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 13:01
  • Fix: TranslatePress compatibility. On a site running TranslatePress
    (the other major free multilingual plugin besides Polylang), every URL
    under a non-default language's prefix — /fr/some-post/, /fr/category/ news/, the /fr/ homepage, all of it — was ccc_unresolvable. This
    wasn't a narrow edge case like Polylang's homepage gap; it was every
    translated URL on the whole site. Root cause, verified against
    TranslatePress's own source rather than assumed: it manages its
    language-prefixed URLs (includes/class-url-converter.php) with plain
    string manipulation, not a WordPress rewrite rule — there is no
    add_rewrite_rule() call anywhere in the plugin. url_to_postid() and
    CCC_Term_Resolver's own rewrite-rule matching both work by matching
    against WordPress's compiled rewrite rules, so a prefix that isn't one
    of those rules is invisible to them, full stop.

  • Architecturally, TranslatePress turned out to be the OPPOSITE problem
    shape from Polylang: Polylang creates genuinely separate content (a real
    post_id per translation) plus a real (if non-public) taxonomy whose
    rewrite rule could collide with CCC's own resolution — see 0.8.1.
    TranslatePress has no separate content or SEO storage per language at
    all; it translates the SAME post's SAME Yoast/Rank Math postmeta at
    render time via its own gettext-style string dictionary, keyed on the
    literal original string text. That makes the fix simpler than Polylang's:
    CCC_Service::strip_translatepress_language_prefix() recognises and
    strips a configured non-default language's URL slug (read from
    TranslatePress's own trp_settings option — it ships no public @api
    equivalent of Polylang's pll_home_url()) before any resolution runs, so
    every existing post/term/homepage path handles the stripped URL exactly
    like its default-language counterpart. No REST contract change: lang
    stays empty throughout, correctly — there is nothing per-language here
    for it to mean.

  • Verified end-to-end against a real WordPress + Yoast + TranslatePress
    install, not source-reading alone (tests/integration/ translatepress-checks.sh, 9/9): a post URL and its /fr/-prefixed
    counterpart resolve to the same post_id; the homepage and its /fr/
    counterpart both resolve to HOME_ID; a CCC title write is read back
    identically from either URL. Confirmed the harness genuinely catches the
    regression by reverting the fix locally first (5/9 failed, as predicted).

  • One consequence documented, not fixed, because it isn't a CCC bug: since
    TranslatePress's translation lookup is keyed on the literal original
    string, ANY edit to that string — from CCC or from a site owner's own
    hand-edit in Yoast's metabox, no difference — orphans whatever
    translation already existed until a human re-translates it in
    TranslatePress's own editor. Noted in SECURITY-NOTES.md so it isn't
    rediscovered as "a bug" later.

  • Security: the lang field shipped in 0.9.0 was never added to
    security-checks.sh's type/injection/unicode/null-byte/oversized-string
    fuzzing matrix every other field gets. Added 12 checks to
    polylang-yoast-home-checks.sh (the one harness with Polylang+Yoast
    live) — no bug found, is_string() + a strict in_array() whitelist
    already rejected everything; now a permanent regression check.

  • Packaging (30 Sept, before this version was tagged): bin/build-zip.sh
    builds the installable crawl-cove-connector.zip from the same
    production file set tests/integration/plugin-check.sh checks (one
    exclude list now, shared), verifies the archive unpacks under
    crawl-cove-connector/ with no tests/vendor inside, and refuses to build
    if the plugin header, CCC_VERSION, readme Stable tag and this
    changelog disagree. A tag push (v*) now creates the GitHub Release with
    that zip attached (.github/workflows/release.yml). Installation step 1
    in readme.txt/README.md names the download; the "a few hundred lines"
    size claim is gone (the plugin is about two thousand lines of PHP now).