Release notes

What changed in GrabWP

Release history is compiled from each plugin's readme.txt. Every entry below reflects a snapshot of those source files.

Source of truth

The plugin readmes are authoritative. This page is refreshed when a release is published.

Base plugin

GrabWP Tenancy

Current stable version: v1.1.4

Release history: 17

v1.1.4

  • New: Performance & Security settings tab applies per-tenant constants: `DISABLE_WP_CRON`, XML-RPC off, `WP_POST_REVISIONS`, `EMPTY_TRASH_DAYS`, and `WP_HTTP_BLOCK_EXTERNAL` with a `WP_ACCESSIBLE_HOSTS` allowlist
  • New: Path routing prefix is configurable - `/site/{tenant-id}` becomes `/{prefix}/{tenant-id}` across rewrite rules, `.htaccess`, admin URLs, and the status page, via `GRABWP_TENANCY_PATH_PREFIX` (defaults to `site`)
  • New: Tenant URLs resolve Pro path aliases through `grabwp_tenancy_get_tenant_path_slug()`, so homepage and dashboard links use the alias when one is set
  • New: Status page warns about path confusion - duplicate `tenants.php`, `config.php`, or `tenant-aliases.php` copies, data directories inside `uploads/`, and directory constants hardcoded in `wp-config.php`
  • Enhance: Settings support integer and text values in addition to checkboxes, sanitized per type and written correctly to the settings file
  • Enhance: Settings screen split into tabs, with the active tab remembered between visits
  • Enhance: Base directory detection honors `GRABWP_WORDPRESS_CONTENT_DIR` and the `wp-content/grabwp-tenancy/tenants.php` location
  • Enhance: `.htaccess` rules and status checks accept alias slugs while still recognizing the legacy 6-character rule
  • Change: The SQLite integration plugin is hidden from plugin lists - activating or deactivating it breaks every SQLite-backed site
  • Fix: Duplicate "Settings saved successfully" notice on the settings page

v1.1.3

  • Enhance: Tenant detection now supports `GRABWP_TENANCY_TENANT_ID` env var for CLI boot without wp-config constants
  • Enhance: CLI tenant context auto-populates `HTTP_HOST` and `HTTPS` from tenant mappings when missing
  • Enhance: WP-CLI `$table_prefix` synchronization - file-scope global re-bind prevents stale prefix after eval
  • Enhance: CDN URL included in database export metadata when Pro storage is configured
  • Enhance: Tenant list table uses natural column widths for better extension compatibility
  • Enhance: Responsive CSS for tenant list on mobile screens
  • Fix: `UPLOADS` constant only defined when upload dir is inside ABSPATH, preventing path resolution errors on custom layouts
  • Fix: Server info cache can be reset via `grabwp_tenancy_reset_server_info_cache()` after environment changes

v1.1.2

  • Security: Replaced the file-based admin access token (a secret written to `tokens.php` and consumed via rename) with stateless HMAC-SHA256 tokens bound to the tenant ID, signed with `AUTH_KEY`/`AUTH_SALT` and given a short TTL (default 30 minutes, configurable via `GRABWP_TENANCY_TOKEN_TTL`). No token secret is persisted to disk anymore.
  • New: The clone "complete" screen now shows the target tenant ID with quick links to Edit tenant, Homepage, and Dashboard.
  • Enhance: Admin UI refactor - inline styles moved into a shared stylesheet (`admin/css/grabwp-admin-shared.css`) with utility classes; section show/hide now toggles a `hidden` class.
  • Change: Clone pipeline reordered - site URL replacement now runs before copying uploads.
  • Change: Installer removes legacy `tokens.php` / `.consumed` artifacts on activation; removed the now-unused `get_tokens_file_path()` helper.

v1.1.1

  • Security: Admin access tokens are now **single-use** - consumed atomically on first successful login; concurrent or replayed token requests are rejected.
  • Security: Domain hash validation is mandatory for admin token login; comparisons use timing-safe `hash_equals()`.
  • Security: Path-based admin URLs no longer expose `tenant_domain` in the query string; hash validation uses internal routing context instead.
  • Enhance: Added `GrabWP_Tenancy_Path_Manager::atomic_put_php_file()` for atomic writes of settings, tenant mappings, and admin token files (tmp + rename, ABSPATH guard, OpCache invalidation).
  • Fix: Tenant clone file copy now skips symlinks, preventing accidental duplication of shared plugin/theme directories.
  • Fix: WordPress cron requests again run in mainsite context (tenant detection disabled during `DOING_CRON`).

v1.1.0

  • Refactor: Split early-boot `load-helper.php` into focused modules (security, server detection, tenant detection, boot constants, cache) - same boot behavior, easier maintenance and extension.
  • Refactor: Extracted admin form handling, tenant CRUD, and domain validation into dedicated classes (`GrabWP_Tenancy_Admin_Form_Handler`, `GrabWP_Tenancy_Tenant_Crud`, `GrabWP_Tenancy_Domain_Validator`); public `handle_create_tenant()`, `handle_update_tenant()`, and `handle_delete_tenant()` methods remain for backward compatibility.
  • Refactor: Status page reorganized into tab partials with centralized environment checks via `GrabWP_Tenancy_Status_Checker` (General, Base Plugin, Pro Plugin tabs unchanged).
  • Fix: Settings page now shows the "Settings saved successfully." notice after saving (previously redirected but notice was never displayed).
  • Developer: All existing action hooks (`grabwp_tenancy_before_create_tenant`, `grabwp_tenancy_after_create_tenant`, etc.) preserved; no migration required.

v1.0.11

  • New: **Cache isolation for tenant context** - disables page-cache drop-ins per tenant request (`WP_CACHE`) and prefixes object-cache keys with the tenant ID (`WP_CACHE_KEY_SALT`) to prevent cross-tenant cache collisions on shared Redis/Memcached backends.
  • New: Added `grabwp_tenancy_get_tenant_url()` helper to resolve a tenant front-end URL by ID without loading a full tenant object.
  • Enhance: Centralized tenant URL resolution - `get_site_url()`, `get_admin_access_url()`, and static helpers (`resolve_site_url()`, `resolve_admin_url()`, `build_site_url()`) now handle domain-based and path-based routing in one place; tenant list and clone flows use these shared methods.
  • Enhance: Log messages are automatically prefixed with `[tenant_id]` or `[Mainsite]` for easier multi-tenant debugging.

v1.0.10

  • Fix: Tenant directory cleanup now handles symlinks safely during recursive deletion, removing only the symlink itself instead of following it into the original shared plugin or theme directory.
  • Enhance: Tested up to WordPress 7.0.

v1.0.9

  • Fix: Default tenant data directory moved from `wp-content/uploads/grabwp-tenancy` to `wp-content/grabwp-tenancy` (outside uploads) to prevent direct web access to tenant data. Existing installs that already use the uploads path are preserved automatically - no migration needed.
  • Fix: Corrected legacy-path migration notice in the Status page to use `WP_CONTENT_DIR` directly instead of `wp_upload_dir()`, matching the new default path.
  • Fix: Downgraded oversized "Clone to existing site" / "Clone to new site" hero buttons on the clone page to standard buttons for visual consistency.
  • Enhance: Plugin/theme admin bar nodes (`plugins`, `themes`) are now removed on tenant sites when the corresponding Hide Plugin Management / Hide Theme Management settings are enabled, closing a gap where the toolbar still exposed those links.
  • Enhance: Tenant create page UX - the first domain field is now auto-filled with a suggested domain (`tenant-{6digits}.{hostname}`); a new **Clear** button lets users wipe the field quickly; the domain input grows up to 500 px wide; and the domain section is visually indented under its radio button.
  • Enhance: GrabWP Tenancy admin menu position moved higher (position 3) so it appears near the top of the sidebar.
  • Change: Default values for **Hide Plugin Management** and **Hide Theme Management** settings changed from `true` to `false` for fresh installs, giving new tenants full access by default until explicitly restricted.

v1.0.8

  • New: **Tenant Cloning** - clone any existing tenant (or the mainsite) to a new tenant, including database tables and uploaded files with automatic URL replacement.
  • New: Added `GRABWP_MAINSITE_ID` constant (`__mainsite__`) to allow the main site to be used as a clone source.
  • Enhance: Mainsite domain detection now supports localhost and local-network domains that have no TLD extension (e.g., `mysite.local`, bare `localhost`).
  • Fix: Resolved plugin asset URL resolution on hosts where the plugin directory is symlinked - switched to `content_url()` to avoid incorrect absolute paths.
  • Fix: Refactored tenant ID generation to guarantee uniqueness and avoid collisions on busy installations.
  • Quality: Normalised all PHP source files from CRLF to LF line endings.

v1.0.7

  • Major: Introducing **Path-Based Routing**! You can now host tenants on subdirectories/paths (e.g., `example.com/site/abcdef`) without requiring separate domains. This completely eliminates the need for complex domain mappings and serves as a true, lightweight replacement for WordPress Multisite.
  • Enhance: Added comprehensive `.htaccess` diagnostic admin notices specifically tailored for path-based routing support.
  • Enhance: Centralized configuration and diagnostic tools into a transparent, read-only Status Page UI with manual fallback instructions for environment issues.
  • Refactor: Streamlined the installation, uninstallation, and environment-fixing processes into a single `GrabWP_Tenancy_Installer` class.
  • Security: Improved code compliance by integrating complete nonce verification on sensitive administrative handlers and securely transitioning to `wp_is_writable()`.
  • Fix: Resolved PHP fatal errors (e.g., `Class Not Found`) relating to the class autoloader sequence during the initial activation process.
  • Quality: Standardized codebase formatting for consistent line endings (CRLF to LF) and file encoding across all files.

v1.0.6

  • New: Dedicated **Status** admin page with system information, file structure, database config, content isolation, and domain routing details (moved out of Settings page)
  • New: One-click **Auto Install MU-Plugin** button with AJAX handler - auto-creates the must-use plugin file, or shows copy-to-clipboard fallback when the directory is not writable
  • New: One-click **Auto Install to wp-config.php** button with AJAX handler - injects the `load.php` require line before the stop-editing marker, or shows copy-to-clipboard fallback when `wp-config.php` is not writable
  • New: Admin notices for missing MU-plugin and missing `wp-config.php` loader, shown only on plugin pages, with writability-aware UI (auto-install vs. manual copy)
  • New: Pro Features section added to the plugin readme
  • Improved: Default tenant capability settings are now **enabled** (Disallow File Mods, Disallow File Edit, Hide Plugin Management, Hide Theme Management) for stronger security out of the box
  • Improved: Added fallback definition of `grabwp_tenancy_validate_tenant_id()` in Path Manager so validation works even when `load-helper.php` is not loaded
  • Improved: Tenant edit page title now displays the tenant ID for clarity
  • Improved: Moved AJAX nonces (`muPluginNonce`, `loaderNonce`) into localized admin script data
  • Improved: Refactored JS - extracted `bindCopyButton()` helper, added `initMuPluginInstall()` and `initLoaderInstall()` handlers in `grabwp-admin.js`
  • Improved: Streamlined `load-helper.php` base-dir resolution logic and added `GRABWP_TENANCY_DIRS_FROM_PLUGIN` constant
  • Improved: Renamed local variables in tenant views to use `grabwp_tenancy_` prefix to avoid potential conflicts
  • Improved: Tested up to WordPress 6.9

v1.0.5

  • New: Settings page for tenant capability controls (Disallow File Mods, Disallow File Edit, Hide Plugin Management, Hide Theme Management, Hide GrabWP Plugins)
  • Fix: Tenant ID starting with a number causes database errors on table prefix

v1.0.4

  • Enhance tenant management with a new list table for admin
  • Implement logging functionality, and improve tenant deletion process with confirmation prompts.
  • Refactor path management and database handling for better organization and security.
  • Update translations and enhance admin UI elements for improved user experience.
  • Refactor tenant initialization process to streamline functionality for tenant and main site.
  • Remove deprecated asset loading class and configuration management.
  • Enhance tenant context handling and improve upload directory management.
  • Introduce hooks for pro plugin extensibility and improve code organization for better maintainability.

v1.0.3

  • **Major Enhancement**: Added comprehensive early loading system with load-helper.php
  • **Security Improvements**: Enhanced input sanitization and validation functions for early loading
  • **Path Management**: Introduced centralized Path Manager with backward compatibility support
  • **WordPress Compliance**: Improved path structure with fallback to WordPress-compliant uploads directory
  • **CLI Support**: Added command-line interface support for tenant operations
  • **Performance**: Optimized tenant detection with caching and reduced file system calls
  • **Backward Compatibility**: Maintained support for existing wp-content/grabwp structure

v1.0.2

  • Improved tenant management interface
  • Direct login button to tenant from main site admin (If plugin also activated on tenant)
  • No longer access to plugin admin page and menu from tenant's admin dashboard

v1.0.1

  • Refactored core plugin for improved tenant management and protocol handling
  • Added admin notice registration for better user feedback in the admin area
  • Defined GRABWP_TENANCY_LOADED constant for reliable plugin load detection
  • Added translation support by loading the plugin text domain on initialization
  • Added Vietnamese language support

v1.0.0

  • Initial release
  • Basic multi-tenant functionality
  • Domain-based routing
  • Admin interface for tenant management
  • Shared MySQL with tenant prefixes
  • Separated upload directories