Skip to content
Gaurav TiwariChangelog

All products

Changelog

Every release across our products, newest first.

RSS feed

Showing 181–192 of 542 releases

  1. Stable

    GT Performance 1.0.1

    The compiled cache configuration and the Redis runtime configuration are no longer executable PHP. Both are stored as JSON behind a fixed <?php exit; ?> guard line and are read with file_get_contents() and json_decode(), never…

    Read full notes 19 changes
    • Security
    • The compiled cache configuration and the Redis runtime configuration are no longer executable PHP. Both are stored as JSON behind a fixed <?php exit; ?> guard line and are read with file_get_contents() and json_decode(), never included. The guard keeps a direct web request from disclosing the Redis credentials on servers that do not honour .htaccess.
    • The early cache drop-in and RequestContext::fromGlobals() now sanitize the request through one shared implementation. Control characters are stripped and every name and value is bounded before any of it reaches the gt_performance_html filter.
    • Fixed
    • Updating from 1.0.0 took the whole site down. The drop-in published by that release loads a fixed list of runtime files that predates ConfigFile, so the moment the new plugin files landed it fatally errored inside wp-settings.php — before WordPress exists to catch it — taking the front end and wp-admin down together with no way back except filesystem access. DropinRuntime::serve() now loads its own dependency when an older drop-in did not.
    • Schema 3 renames this plugin's tables from the gtp_ prefix to gtperf_. Without a schema bump the upgrade left the old tables in place and every queue, dependency, and CSS artifact query failed against a table that did not exist. The upgrade now creates the renamed tables and drops the superseded ones.
    • WpCacheConstant::enable() rewrote an already-correct WP_CACHE line to an identical value, read the unchanged file as a failed update, and returned an error — which made DropinInstaller::install() delete the drop-in it had just published. Installing twice in a row disabled page caching.
    • DropinInstaller::syncVersion() gated only on the version, so a migrated or restored site running the same release from a new path kept a compiled configuration naming the old directory. The drop-in found nothing to load and the site served uncached indefinitely without reporting anything. The gate now tracks the location alongside the version.
    • Keyboard focus styles were pruned out of generated CSS. :focus-visible and :focus-within matched the shorter focus alternative in the dynamic-state pattern, leaving -visible and -within fused to the class name, so the rules matched nothing and were removed as unused.
    • RequestContext::fromGlobals() did not unslash the superglobals, so any URL, query value, or cookie containing a quote hashed differently in WordPress than in the drop-in and could never produce a cache hit.
    • DropinInstaller::installedVersion() captured the trailing period after the drop-in signature, which made every version comparison unequal and reinstalled the drop-in on each request.
    • Changed
    • Page-cache entry metadata is now <hash>.meta.json instead of a generated <hash>.meta.php. Because metadata no longer passes through opcache, the opcode-invalidation workaround is gone along with the stale-metadata window it covered on hosts running opcache.validate_timestamps=0.
    • advanced-cache.php is a bundled file copied verbatim from dropins/, with only its version stamped in. It resolves the cache root from WP_CONTENT_DIR and the plugin directory from the compiled configuration, so no path is baked into the published drop-in.
    • Every output buffer the plugin opens is closed explicitly through Core\OutputBuffer, on shutdown at priority 0, ahead of core's own wp_ob_end_flush_all().
    • Renamed the GTP_ and gtp_ prefixes to GTPERF_ and gtperf_ across constants, transients, AJAX actions, the cron schedule, the Private Islands shortcode, and the Redis key prefix. There is no compatibility shim: wp-config.php constants and any stored shortcode must use the new names.
    • Updated sabberworm/php-css-parser from 8.9.0 to 9.4.0. Version 9 requires thecodingmachine/safe at runtime, which adds about 2.4 MB to the package and eagerly loads 79 function-definition files when the plugin bootstraps. That cost lands only on full WordPress requests, measured at roughly 5 ms; requests served from the page cache never load the plugin autoloader and are unaffected.
    • The compiled configuration files are now config.json.php and redis-config.json.php. The names deliberately differ from the config.php and redis-config.php used up to 1.0.0: a drop-in left over from that release reads those paths with require, so pointing the new guarded files at the old names could have blanked every front-end response if the drop-in swap did not complete. Compiling also deletes the old files.
    • dropins/ is now covered by the coding-standards run.
  2. Stable

    GT Performance 1.0.0

    Changed

    Read full notes 5 changes
    • Changed
    • First stable release, distributed free through the WordPress.org plugin directory.
    • Removed FluentCart licensing and the custom updater. Plugin updates now arrive through the normal WordPress.org update flow with no license key, activation, or weekly verification cron. The License tab, its admin-post actions, and the gt_performance_verify_license schedule are gone; deactivation and uninstall clean up state left by earlier licensed builds.
    • Fleet Console no longer requires a license. Policy bundles are signed with a key derived from a shared fleet signing secret saved on each site (encrypted at rest) or defined as GTPERF_FLEET_SIGNING_SECRET in wp-config.php. The secret itself is stripped from exported bundles.
    • Uninstall now also removes the fleet site identity and event log options.
  3. Stable

    GT ACF Blocks Plugin 2.11.0

    Inlined block stylesheets shipped unminified source. acf_blocks_minify_loader_src() only runs when a sheet is printed as a <link>. Styles registered from block.json also carry path data, and wp_maybe_inline_styles() reads that…

    Read full notes 19 changes
    • What's Changed
    • Fixed
    • Inlined block stylesheets shipped unminified source. acf_blocks_minify_loader_src() only runs when a sheet is printed as a <link>. Styles registered from block.json also carry path data, and wp_maybe_inline_styles() reads that file straight off disk and prints its bytes into the page without the URL ever reaching style_loader_src — so every page rendering one of those blocks carried the readable source. It hit the four blocks whose block.json declares style as an array (Callout, Feature Grid, Post Display, Table of Contents); a string style is pre-registered by acf_blocks_register_styles() under the handle WordPress would have generated, so core bails before attaching path. acf_blocks_minify_registered_styles() now rewrites both src and path on plugin-owned registrations before the inline pass. Rewriting the registration rather than the printed tag keeps the inlining, so pages still avoid the extra request and just carry less of it — measured on a published Table of Contents post, 2,279 inlined bytes down to 1,494.
    • ACF blocks now keep their baseline rhythm in the block editor. acf_blocks_register_layout_styles() attaches tokens.css and block-layout.css with wp_enqueue_block_style(), which only fires when a block renders on the front end — the editor canvas never received them. A heading following a Table of Contents block sat flush against it while editing and had 1.5rem of air once published. The sheets are now also enqueued on enqueue_block_assets in admin, the hook WordPress injects into the canvas document. Front-end delivery still goes through wp_enqueue_block_style(), so pages only pay for the sheets when a block is actually present.
    • block-layout.css matches the editor's markup. The front end renders the block element itself carrying .acf-block, while the editor wraps the same output in .wp-block and puts acf-block-component / acf-block-<name> on the wrapper — so .acf-block matched nothing inside the canvas even once the sheet loaded. The rule now carries a second selector for the wrapper. The two cannot match the same element, so the margin is never doubled. That second selector deliberately does not use :where(): the block editor sets its own margins on .wp-block elements, so a zero-specificity rule loses to them. Measured on a Table of Contents block followed by a heading — 0px with :where(), 24px without, against 24px on the published page.
    • Commits
    • 2.11.0: serve minified CSS for inlined block stylesheets (ae06e79)
    • Stats
    • Commits: 1
    • Changes 7 files changed, 212 insertions(+), 4 deletions(-)
    • Plugin Info
    • Blocks included: 29
    • Requires WordPress: 6.0+
    • Requires PHP: 7.4+
    • Requires: ACF Pro 6.0+ or Secure Custom Fields
    • Installation
    • Download acf-blocks-plugin-*.zip from the assets below
    • Go to Plugins → Add New → Upload Plugin in WordPress admin
    • Upload the zip file and activate
  4. Stable

    GT Extensions for FluentCart 2.4.1

    Patch release for 2.4.0.

    Read full notes

    Converts product prices a theme renders itself. 2.4.0 made the storefront currency symbol follow the visitor's selection, so the cart drawer would stop labelling converted amounts with the store currency's sign. Prices inside FluentCart's own blocks were converted to match — but a theme can render a product price too, reading the cached price span straight from the database and formatting it with FluentCart's helper. No filter can reach a number obtained that way, so such a price showed the right symbol against an unconverted amount.

    Single product pages are now transcoded in one pass over the whole response, which covers theme and third-party output as well. The page pass and the per-block passes are mutually exclusive, so nothing is converted twice, and the buffer returns the original markup on any error rather than swallowing the page.

    Also maps the stored price-span columns, so a product whose cached span has drifted from its variations still converts.

    Everything in 2.4.0 is included.

  5. Stable

    GT Extensions for FluentCart 2.4.0

    Seven hooks were registered under names FluentCart does not use:

    Read full notes 11 changes

    Requires FluentCart 1.5.5 or newer. Verified against FluentCart 1.6.1.

    • Multi-currency correctness
    • Cart totals were converted twice. FluentCart fires cart/can_purchase before cart/item_price against the same in-memory variation, so the price filter re-applied the exchange rate to an already-converted amount and a ₹480.00 line rendered as ₹46,219.00.
    • Every product-page price now converts, not only the one FluentCart exposes a filter for. The compare price, header price range, and variant cards previously kept store-currency amounts, so a converted price sat beside an unconverted one. Manual price-book entries still win over the exchange rate.
    • The currency symbol follows the selection across the whole storefront, not just checkout, so the cart drawer no longer labels converted amounts with the store currency's sign.
    • Receipts and order confirmations report the currency the order was charged in. FluentCart's receipt renderer formats every amount with no currency argument.
    • Features that were silently disabled: Seven hooks were registered under names FluentCart does not use:
    • cart/validate_add and cart/validate_update do not exist — can_purchase is the gate Cart::addItem() actually runs, so minimum/maximum quantity limits and guest purchase blocking were enforced only in the browser and a direct cart request bypassed them.
    • fluent-cart/product_stock_availability was hyphenated; product/buy_now_text, product/show_add_to_cart, variation/data and admin_js_vars do not exist at all.
    • is_singular('fct_product') tested a database table prefix rather than a registered post type, so module CSS printed on every page of the site while the matching scripts ran on none.
    • External Product admin screen: Rebuilt: saves over AJAX with inline status (the no-JS form post still works), card layout, dependent fields that disable while redirection is off, client-side URL validation, a live button preview, and a readout of the exact rel attribute that will ship. FluentCart's product navigation is now styled, since FluentCart does not load its admin stylesheet on a custom submenu page.
    • Performance: A variation's whole price book is read in one query and reused. The currency selector's stylesheet, script and cart lookup load only where a price can appear, and its uncacheable status request no longer fires on pages with no selector.
  6. Stable

    Alpha Chat 0.5.0

    Launcher offset. Four new fields under Settings → Launcher set how far the floating button and panel sit from the bottom and side of the screen, in pixels, with separate values for desktop and mobile. The launcher was pinned 20px from the…

    Read full notes 2 changes
    • Added
    • Launcher offset. Four new fields under Settings → Launcher set how far the floating button and panel sit from the bottom and side of the screen, in pixels, with separate values for desktop and mobile. The launcher was pinned 20px from the edges, so on themes with their own fixed bottom bar — a mobile nav, a share row, a cookie strip — it covered the controls underneath it and there was no way to move it. Values are clamped to 0-400px, and the panel's height subtracts the bottom offset so raising the widget cannot push the panel off the top of the screen. Defaults reproduce the previous position exactly. Applied as CSS custom properties evaluated per visitor, so the desktop/mobile split stays correct behind a full-page cache.
  7. Stable

    Alpha Chat 0.4.1

    Fatal error when the plugin update cache was cleared. clear_update_cache() is hooked on delete_site_transient_update_plugins and deleted that same transient, which fired the action again; the hook re-entered itself until PHP exhausted…

    Read full notes 2 changes
    • Fixed
    • Fatal error when the plugin update cache was cleared. clear_update_cache() is hooked on delete_site_transient_update_plugins and deleted that same transient, which fired the action again; the hook re-entered itself until PHP exhausted memory ("Allowed memory size exhausted"). Any code path that deletes the update_plugins site transient triggered it, including wp plugin list after a cache flush. The method now holds a re-entry guard.
  8. Stable

    Alpha Chat 0.4.0

    Error log. Errors and warnings are recorded to a new table and shown under Alpha Chat → Logs, with level filter, expandable context, source attribution, and a clear button. Provider failures used to be invisible unless the site owner read…

    Read full notes 12 changes
    • Added
    • Error log. Errors and warnings are recorded to a new table and shown under Alpha Chat → Logs, with level filter, expandable context, source attribution, and a clear button. Provider failures used to be invisible unless the site owner read the PHP error log. Anything resembling a credential is stripped before an entry is stored, and entries are pruned daily to 30 days and 2000 rows.
    • AI conversation titles. Conversations are named from their opening exchange by the configured chat provider, replacing a truncation of the first message. Runs as a scheduled action with a 24-token budget, so it never delays or endangers a reply, and each conversation is named once. Toggle under Behavior.
    • Per-device launcher visibility. The floating button can be shown or hidden independently on desktop, tablet, and mobile. Applied by screen width in the browser, not by server-side user-agent detection, so it stays correct behind a full-page cache. Blocks and shortcodes are unaffected.
    • alpha_chat_pre_llm_provider and alpha_chat_pre_embedding_provider filters, which replace a provider before the built-in one is constructed. The existing alpha_chat_llm_provider filter can only decorate an instance that already exists, so swapping in your own provider previously still required configuring an API key for a built-in provider you were not using.
    • alpha_chat_log_retention_days, alpha_chat_log_max_rows and alpha_chat_thread_titled hooks.
    • Fixed
    • A conversation showed 0 messages and a bare uuid in the admin whenever a reply failed. The message count and title were only written after a successful completion, even though the visitor's message had already been stored. Both are now written when the message is stored, and the count is derived from the stored rows.
    • Fallback titles contained a literal … entity instead of an ellipsis.
    • Provider and configuration failures return HTTP 503 rather than 502. A CDN in front of the site replaces a 502 body with its own error page, so the actual reason never reached the widget or the site owner.
    • Database
    • Schema 1.6.0 adds the alpha_chat_logs table and a title_generated column on alpha_chat_threads. Applied automatically on upgrade.
  9. Stable

    Alpha Chat 0.3.2

    Assistant replies showed raw Markdown. Models answer in Markdown, but the widget rendered the reply as plain text, so visitors saw literal bold and - bullets instead of formatting. Replies now render bold, italic, inline code, fenced…

    Read full notes 6 changes
    • Fixed
    • Assistant replies showed raw Markdown. Models answer in Markdown, but the widget rendered the reply as plain text, so visitors saw literal **bold** and - bullets instead of formatting. Replies now render bold, italic, inline code, fenced code blocks, links, headings, and bullet and numbered lists.
    • Security
    • The Markdown renderer builds React elements rather than an HTML string, so reply text — which is shaped by retrieved site content and curated Q&A — can never inject markup. The widget still contains no dangerouslySetInnerHTML. Links are restricted to http, https and mailto; a javascript: URL renders as plain text and every link carries rel="noopener noreferrer".
    • Notes
    • A visitor's own message is still rendered verbatim, not as Markdown.
  10. Stable

    Alpha Chat 0.3.1

    Chat failed with every reasoning model. The stored temperature was sent on each request, and reasoning models (gpt-5*, o1*, o3*, o4*) reject any sampling value other than the default, failing the whole request with 'temperature' does not…

    Read full notes 4 changes
    • Fixed
    • Chat failed with every reasoning model. The stored temperature was sent on each request, and reasoning models (gpt-5*, o1*, o3*, o4*) reject any sampling value other than the default, failing the whole request with 'temperature' does not support 0.7 with this model. temperature, top_p, presence_penalty and frequency_penalty are now omitted for those models instead of being sent with a value they refuse. Conventional models such as gpt-4o are unaffected and still receive the configured values.
    • Added
    • alpha_chat_is_reasoning_model filter, for a model the bundled prefix list does not cover yet.
  11. Stable

    Alpha Chat 0.3.0

    Security and correctness release from a full audit of the plugin. Please read the upgrade notes below if your site sits behind a proxy other than Cloudflare, or if anything calls the contact endpoint directly.

    Read full notes 34 changes
    • Security
    • Rate limiting no longer trusts X-Forwarded-For from arbitrary callers. The header was accepted unconditionally, so rotating it gave every request its own bucket and left provider spend effectively uncapped. Forwarding headers are now honoured only when the request actually arrives from a trusted proxy. Cloudflare's published edge ranges are trusted out of the box; anything else is declared with the ALPHA_CHAT_TRUSTED_PROXIES constant or the alpha_chat_trusted_proxies filter.
    • Added a site-wide chat and contact ceiling that no client-supplied identifier can partition, as a backstop on total provider spend.
    • POST /contact now requires a valid wp_rest nonce. It was previously open to unauthenticated callers and sent mail on every request.
    • Resuming a conversation now requires the caller to own it. A thread uuid alone used to be enough, and history is replayed into the prompt, so a leaked uuid exposed the earlier conversation.
    • The current-page context injected into the prompt is now restricted to this site. An off-site origin_url with an attacker-chosen origin_title could previously write arbitrary text into the system prompt.
    • Transcript CSV export now neutralises spreadsheet formula injection from visitor-authored message content.
    • Masked API keys are a fixed width and no longer reveal the real key length.
    • Fixed
    • A single chat message could trigger more than one paid completion. The widget retried across transports after the server had already answered, duplicating both the provider charge and the stored thread history. It now retries only when the request never reached the plugin.
    • Transcript CSV export returned a JSON-encoded string rather than a CSV file, so the download could not be opened as a spreadsheet. It now streams real CSV, row by row, and no longer loads the whole archive into memory.
    • The "Add to Alpha Chat" post row action rendered a button whose handler was never loaded, so clicking it did nothing.
    • Stored API keys could not be cleared from the settings screen.
    • A chat widget on a cached page recovers from an expired nonce instead of failing with a message that a reload could not fix.
    • Restoring a post from the trash returns it to the knowledge base.
    • delete_post no longer runs knowledge-base cleanup for revisions and autosaves.
    • Update checks cache failures, so an unreachable licence server no longer adds a blocking request to every admin page load.
    • Token counting handles CJK text, which was undercounted roughly fourfold and produced oversized chunks.
    • Follow-up detection no longer treats every short message as a follow-up, which was dragging the previous topic into retrieval after a clean subject change.
    • Uninstall cleans every site on a multisite network and unschedules its Action Scheduler jobs; network activation installs tables on every site.
    • Changed
    • Curated Q&A is now ranked against the question and capped before it enters the prompt, instead of sending every enabled entry on every message.
    • Settings are resolved once per request rather than rebuilt on each read.
    • Retrieval scans a bounded candidate set when the fulltext index returns nothing.
    • Errors and warnings are logged without requiring WP_DEBUG.
    • Outbound fetches for the FAQ importer go through wp_safe_remote_request, and the pre-flight check covers IPv6 and literal addresses.
    • The settings response reports whether moderation is actually active, which requires an OpenAI key regardless of the chat provider.
    • Added
    • alpha_chat_trusted_proxies, alpha_chat_trust_cloudflare, alpha_chat_rate_limit, alpha_chat_max_prompt_faqs, alpha_chat_fallback_candidates, alpha_chat_max_queued_posts and alpha_chat_should_log filters.
    • GET /nonce for widgets on cached pages.
    • Upgrade notes
    • Behind Cloudflare, nothing to do. Behind any other proxy or load balancer, declare it or anonymous visitors will share rate-limit buckets: define( 'ALPHA_CHAT_TRUSTED_PROXIES', '10.0.0.0/8' );
    • Anything posting to /alpha-chat/v1/contact must now send an X-WP-Nonce header.
    • ChatController::is_rate_limited() is deprecated in favour of AlphaChat\Support\RateLimiter::hit().
  12. Stable

    Alpha Chat 0.2.1

    Public chat no longer dies with Unexpected token '<' when /wp-json/ returns HTML. The widget retries ?rest_route=/alpha-chat/v1/chat and shows a retry message instead of the fallback answer plus a parse dump.

    Read full notes 5 changes
    • Fixed
    • Public chat no longer dies with Unexpected token '<' when /wp-json/ returns HTML. The widget retries ?rest_route=/alpha-chat/v1/chat and shows a retry message instead of the fallback answer plus a parse dump.
    • Changed
    • Dashboard cards, queue tiles, and the activity chart are interactive. Range is 7 / 14 / 30 days.
    • Dashboard uses one GET /dashboard request. Queue polling only runs while jobs are active and the tab is visible.