Skip to content

Licensing and Update API Improvements#1682

Merged
jakejackson1 merged 1 commit into
hot-patch-6.16.0from
hot-patch-6.16.0-updater
Jul 23, 2026
Merged

Licensing and Update API Improvements#1682
jakejackson1 merged 1 commit into
hot-patch-6.16.0from
hot-patch-6.16.0-updater

Conversation

@jakejackson1

@jakejackson1 jakejackson1 commented Jul 22, 2026

Copy link
Copy Markdown
Member

Description

Backports the Licensing and Update API work to the 6.16.0 hot-patch line so Gravity PDF works fully against the new api.gravitypdf.com server. The API URL was already switched, but update checks and license activation still used the legacy edd_action flow the new server no longer matches. This branch migrates the updater and license handling, adds GPDF_LICENSE_KEY support, makes the API traffic Multisite-safe, and redacts secrets from the debug log.

Squashed into a single commit on top of hot-patch-6.16.0.

What's included

Plugin updater

  • Replace EDD_SL_Plugin_Updater with the rewritten, self-contained updater (get_version API, standardize_api_response, gpdf_sl_* cache keys, Multisite changelog / update-notice support)
  • Bootstrap: explicit init(), wp_override on force-check, expose the updater via Helper_Data, log the decoded JSON API response
  • 6.16.0 upgrade routine purges the legacy edd_sl_* update cache and the 6.15.0 failed-request backoff option

License settings + GPDF_LICENSE_KEY constant

  • Move activation / deactivation / delete into the add-on framework (Helper_Abstract_Addon) + bulk license verification
  • Define a license via the GPDF_LICENSE_KEY PHP constant (auto-activation; settings field locked read-only when set)
  • Reworked License settings page + AJAX deactivation (Model_Settings, Controller_Settings, licence-info view, setupLicenseDeactivation.js)
  • Access Pass keys shared across sibling add-ons on activation and deactivation
  • Clear cached licensing data on uninstall (incl. the network-shared gpdf_sl_net_* cache)

Multisite: restrict API checks to the primary site

  • On a network-activated Multisite, WP-Cron runs per-site, so every subsite was independently scheduling its own weekly bulk license check and plugin update check — one API call per subsite (worst case: a network-wide GPDF_LICENSE_KEY makes every subsite hit the API with the same key)
  • Helper_Misc::is_secondary_network_site() reads the active_sitewide_plugins network option, so it's safe in cron / front-end where is_plugin_active_for_network() isn't loaded
  • Gate the bulk license check and the update version check to the primary site; subsites read the network-wide update_plugins transient the primary site populates

Log redaction

  • Redact_Processor (Monolog) masks license keys, signed update / package URLs, tokens, cookies and nonces in the debug log — key-based (recursing into context arrays / objects) plus pattern-scrubbing of message bodies and string leaves, with CRLF / control-char neutralisation to prevent log injection

Post-review hardening (from an expert review of the initial implementation)

  • Prevent a Multisite network-update-check request storm, with a schedule floor to avoid a tight reschedule loop
  • Guard the updater against non-object / scalar / corrupted-cache API payloads (PHP 8 fatal-safety on plugins_api and cached data)
  • Redact string leaves and raw response bodies in log context; add set-cookie to the deny set
  • Sync the cleared license into the in-memory copy when the key is emptied (status / message no longer go stale within the request)
  • Correct expired-license date handling, add-on public-action guards, and docblock / version drift

Scope notes

  • @since markers and the upgrade-routine version gate are set to 6.16.0.
  • Deliberately excluded (separate epics, not needed here): the broader uninstaller-interface refactor, log rotation, and PSR-Log v1/2/3 groundwork.
  • setupLicenseDeactivation.js is a source change — the built asset needs regenerating at release (yarn build).
  • Version constant / changelog reshuffle for 6.16.0 is not part of this PR.

Testing

Automated (PHPUnit, wp-env)

  • Single-site: 1132 tests, 3567 assertions — 0 failures / 0 errors (29 intentional skips)
  • Multisite: 1132 tests, 3639 assertions — 0 failures / 0 errors (2 intentional skips)
  • PHPCS: clean on all changed files

Live / manual — run against production api.gravitypdf.com on a subdirectory Multisite (5 sites, GF 2.10.5), with GF logging on to verify redaction:

  • License activation via the settings field — activates live; status valid
  • Access Pass sibling sharing — activating one add-on auto-activates its pass sibling; an unrelated add-on is left untouched ✓
  • Update check — all four plugins resolve to their correct current versions (no false update, no missing entries, no fatal) ✓
  • Invalid key — clear error surfaced; other add-ons unaffected ✓
  • Empty-key clear — wipes key / status / message in both the DB and the in-memory copy ✓
  • Deactivation — one deactivate clears both Access Pass siblings; DB cleared ✓
  • Log redaction — license key, checksum and nonce all [redacted]; the raw key never appears in plaintext across the full activate → deactivate lifecycle ✓
  • GPDF_LICENSE_KEY constant — auto-activates covered add-ons, fields read-only, correct "not valid for this product" on an uncovered add-on ✓
  • Multisite gating — secondary subsite front-end returns HTTP 200 (no is_plugin_active_for_network fatal) and cron runs clean; is_secondary_network_site skips secondaries / runs on the primary; License tab hidden on secondary sites ✓
  • Uninstaller — removes all options across every site, the network gpdf_sl_net_* cache and the PDF folder structure; deactivation clears all scheduled gfpdf_* cron events ✓

Checklist

  • I've tested the code.
  • My code is easy to read, follow, and understand
  • My code has proper inline documentation / docblocks.

🤖 Generated with Claude Code

@jakejackson1 jakejackson1 changed the title Bring the api.gravitypdf.com plugin updater to the 6.16.0 release Backport the Licensing & Update API (#1624) to the 6.16.0 release Jul 22, 2026
@jakejackson1 jakejackson1 changed the title Backport the Licensing & Update API (#1624) to the 6.16.0 release Licensing and Update API Improvements Jul 22, 2026
@jakejackson1
jakejackson1 force-pushed the hot-patch-6.16.0-updater branch from 2547301 to 5bfc483 Compare July 23, 2026 07:54
Brings the api.gravitypdf.com plugin updater and license management to
6.16.0 (squash of the hot-patch-6.16.0-updater branch):

- Migrate the plugin/add-on updater to the api.gravitypdf.com endpoint and
  backport the license settings overhaul plus the GPDF_LICENSE_KEY constant.
- On network-activated Multisite, restrict license/update API checks to the
  primary site and hide the license notice + License tab on secondary sites.
- Share a licensed add-on package across per-site Multisite installs via a
  network cache, with a self-rescheduling network update check and a 3-day
  package TTL, so unlicensed and primary sites still see and can install the
  update.
- Harden the updater: guard the bulk updater against object injection,
  request storms and null add-ons; redact log secrets; surface license
  deactivation transport failures; retry a stuck hardcoded-license
  activation; and prevent fatals on non-canonical builds and the API-down
  details view.
- Expand multisite test coverage and isolate the tests from subsite-install
  global pollution.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jakejackson1
jakejackson1 force-pushed the hot-patch-6.16.0-updater branch from a3cab08 to ec8fa59 Compare July 23, 2026 22:55
@jakejackson1
jakejackson1 merged commit 34fcb53 into hot-patch-6.16.0 Jul 23, 2026
13 of 14 checks passed
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