You've already forked wc-licensed-product
All checks were successful
Create Release Package / build-release (push) Successful in 1m8s
- New Metrics settings tab with enable/disable toggle - PrometheusController for wp_prometheus_collect_metrics hook - License gauges: total by status, lifetime, expiring, expiring soon - Download gauges: total downloads, active versions - API counters: requests, rate limits, validation errors - Metric tracking in RestApiController and UpdateController Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
40 KiB
40 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
[0.7.4] - 2026-02-03
Added
- Prometheus Metrics Integration: Expose license and API metrics for monitoring
- New "Metrics" settings tab with enable/disable toggle
- License gauges: total by status, lifetime, expiring, expiring soon
- Download gauges: total downloads, active versions count
- API counters: requests by endpoint/result, rate limit exceeded events, validation errors by type
- Requires WP Prometheus plugin
New Files
src/Metrics/PrometheusController.php- Prometheus metrics collection and registration
Technical Details
- Hooks into
wp_prometheus_collect_metricsaction for metric collection - API counters stored persistently in WordPress options (
wclp_prometheus_counters) - Static methods for incrementing counters from API controllers
- Metrics only collected when enabled in settings
[0.7.3] - 2026-02-01
Fixed
- Docker Environment Support: API Verification Secret now visible on customer licenses page in Docker environments
- Added
ResponseSigner::getServerSecret()method to check multiple sources for server secret - Checks PHP constant,
getenv(),$_ENV, and$_SERVERin priority order - Maintains full backward compatibility with standard WordPress installations
- Added
Changed
- Updated
Plugin.phpto useResponseSigner::isSigningEnabled()instead of direct constant check
Technical Details
- Root cause: Docker WordPress setups using
wp-config-docker.phpwithgetenv_docker()don't always define PHP constants - The environment variable was accessible but the constant wasn't being created
- New
getServerSecret()method centralizes all server secret retrieval logic
[0.7.2] - 2026-01-29
Added
- Gitea CI/CD Pipeline: Automated release workflow triggered on version tags
- Automatic package creation with proper WordPress subdirectory structure
- SHA256 checksum generation for package integrity
- Changelog extraction for release notes
- Pre-release detection for hyphenated tags (e.g.,
v0.7.2-rc1)
Changed
- Git Submodule Migration:
magdev/wc-licensed-product-clientis now a git submodule- Located at
lib/wc-licensed-product-clientinstead of being fetched via Composer VCS - Composer now uses
pathtype repository pointing to local submodule - Improves version control clarity and development workflow
- Symlinked to
vendor/duringcomposer install
- Located at
Developer Notes
- New file:
.gitea/workflows/release.ymlfor CI/CD automation - Updated
composer.json: Repository type changed fromvcstopath - Created
.gitmodulesfor submodule tracking - Release packages now exclude
lib/directory (vendor has installed copy) - Submodule checkout required:
git submodule update --init --recursive
[0.7.1] - 2026-01-28
Fixed
- CRITICAL: Fixed API Verification Secret not displayed in PHP fallback template on customer account licenses page
- Response signing now includes
/update-checkendpoint (was missing from signed routes)
Changed
- Updated
magdev/wc-licensed-product-clientdependency to v0.2.2 - Updated
symfony/http-clientdependency to v7.4.5
Technical Details
- Added customer secret display to
displayLicensesFallback()method inAccountController - Added
/update-checkroute toResponseSigner::shouldSign()method for consistent signature headers - Verified server implementation aligns with updated client library documentation
[0.7.0] - 2026-01-28
Security
- Fixed XSS vulnerability in checkout blocks DOM fallback injection
- Unified IP detection for rate limiting across all REST API endpoints
- Added rate limiting to license transfers (5 per hour) and downloads (30 per hour)
- Added file size (2MB), row count (1000), and rate limiting to CSV import
- Added JSON decode error handling in Store API extension
- Added jQuery selector sanitization for license ID validation
Added
- New
IpDetectionTraitfor shared IP detection logic with proxy support - New
RateLimitTraitfor reusable frontend rate limiting - New
src/Common/directory for shared traits
Changed
- RestApiController now uses IpDetectionTrait instead of inline methods
- UpdateController now uses IpDetectionTrait for consistent rate limiting behind proxies
- AccountController now uses RateLimitTrait for transfer rate limiting
- DownloadController now uses RateLimitTrait for download rate limiting
- Checkout blocks fallback uses safe DOM construction instead of innerHTML
[0.6.1] - 2026-01-27
Added
- Filter functionality on customer account licenses page (filter by product or domain)
- Split auto-update settings into two options: "Enable Update Notifications" and "Automatically Install Updates"
- New
isUpdateNotificationEnabled(),isAutoInstallEnabled()static methods in SettingsController - WordPress auto-update filter integration (
auto_update_plugin) for automatic installation
Fixed
- Fixed admin license test popup showing empty product field
handleAjaxTestLicense()now enriches response with product name- Removed version field from test popup (version_id is only set for version-bound licenses)
Changed
- Updated
magdev/wc-licensed-product-clientdependency to v0.2.1 - "Automatically Install Updates" is only selectable when "Enable Update Notifications" is enabled
[0.6.0] - 2026-01-27
Added
- WordPress-style automatic update system for licensed plugins
- Server-side
/update-checkREST API endpoint for WordPress-compatible update information - Client-side
PluginUpdateCheckersingleton for WordPress update integration - New "Auto-Updates" settings subtab with enable/disable and check frequency options
- Secure download authentication via
X-License-Keyheader - Response signing support for tamper-proof update responses
- Configurable cache TTL for update checks (1-168 hours)
Changed
- Updated OpenAPI specification to version 0.6.0 with
/update-checkendpoint documentation
[0.5.15] - 2026-01-27
Fixed
- Fixed tab rendering bug in WooCommerce product edit page when switching to licensed or licensed-variable product types
- Simplified JavaScript to avoid conflicts with WooCommerce's native show/hide logic
- Removed conflicting CSS rule for
.hide_if_licensedthat was causing layout issues - License Settings tab now uses CSS class toggle (
.wclp-active) instead of jQuery.show()/.hide()for proper display - Variations tab now properly shows for licensed-variable products via
woocommerce_product_data_tabsfilter
[0.5.14] - 2026-01-27
Fixed
- CRITICAL: Fixed Product Versions meta box not appearing for licensed-variable products
- Product Versions meta box now always added to product pages, visibility controlled via CSS/JavaScript
- Added
Installer::registerProductTypes()to create product type terms in theproduct_typetaxonomy - Product type terms are now ensured to exist on
woocommerce_inithook for existing installations - Fixed License Settings tab and Product Versions visibility toggling when changing product types
[0.5.13] - 2026-01-27
Fixed
- CRITICAL: Fixed licenses not showing in admin order form for licensed-variable products
OrderLicenseControllernow usesLicenseManager::isLicensedProduct()for consistent product type detection- Fixed expected licenses calculation for variable product orders
- Fixed manual license generation from admin order page for variable products
Changed
- Removed debug logging from all source files (PHP and JavaScript)
- Cleaned up checkout blocks integration, Store API extension, and checkout controller
[0.5.12] - 2026-01-27
Fixed
- CRITICAL: Fixed stock indicator ("1 in stock") appearing in cart for licensed variable product variations
- Override
get_children()with direct SQL query to bypass WooCommerce'sis_type('variable')check - Override
get_variation_attributes()to properly load taxonomy attribute terms - Override
get_variation_prices()to prevent fatal error with null$this->prices_array - Override
get_available_variations()with emptyavailability_htmlfor variations - Added
is_type()override to return true for both 'licensed-variable' and 'variable' type checks - Added multiple stock-related filters:
woocommerce_get_availability_text,woocommerce_product_get_stock_quantity,woocommerce_product_variation_get_stock_quantity - Improved
isLicensedProductOrVariation()check usingWC_Product_Factory::get_product_type()for reliable parent type detection
Changed
LicensedProductVariationnow includesget_availability(),managing_stock(), andis_purchasable()overrides- Simplified
isVirtual()to use sharedisLicensedProductOrVariation()helper
[0.5.11] - 2026-01-27
Fixed
- CRITICAL: Fixed "sold out" message on licensed variable products by correcting
is_purchasable()method - Variable products don't have a direct price -
is_purchasable()now delegates to parentWC_Product_Variableclass - Fixed variation class detection by using product ID parameter instead of unreliable global
$post - Product class filter now properly accepts all 4 WooCommerce filter parameters for reliable variation detection
[0.5.10] - 2026-01-27
Fixed
- Fixed licensed variable products not showing variations even when attributes are defined
- Re-load product via
wc_get_product()to ensure correct class instance is used - Removed overly strict type check that was preventing variations from displaying
- Now mirrors WooCommerce's standard
woocommerce_variable_add_to_cart()implementation
[0.5.9] - 2026-01-27
Fixed
- Fixed frontend error on licensed variable products when no attributes are defined
- Added null checks for
get_variation_attributes(),get_available_variations(), andget_default_attributes() - Show informative message instead of error when product has no variations configured
- Changed product type check from
instanceoftois_type()for better compatibility
[0.5.8] - 2026-01-27
Fixed
- CRITICAL: Fixed critical error on frontend product pages for licensed variable products
- Variable product add-to-cart template now passes required variables (
available_variations,attributes,selected_attributes) - Variants tab no longer disappears when saving attributes on licensed variable products
- Added WooCommerce AJAX event listeners to maintain tab visibility during attribute operations
Changed
- Improved JavaScript event handling for licensed-variable product type in admin
- Added listeners for
woocommerce_variations_loaded,woocommerce_variations_added,woocommerce_variations_savedevents - Added AJAX complete handler for attribute save operations
[0.5.7] - 2026-01-27
Changed
- Removed "Default" prefix from setting labels on Default Settings page for cleaner UI
- Labels now read "Max Activations", "License Validity (Days)", and "Bind to Major Version"
[0.5.6] - 2026-01-27
Fixed
- License Settings tab now only shows for Licensed Product and Licensed Variable Product types
- Previously the tab was visible on all product types due to CSS
!importantoverride
Changed
- Improved JavaScript for License Settings tab visibility handling on product type change
- Updated README.md with complete feature documentation for v0.5.x features:
- Variable Licensed Products
- Multi-Domain Licensing
- Per-License Customer Secrets
- Download Statistics
- Configurable Rate Limiting
[0.5.5] - 2026-01-26
Fixed
- CRITICAL: Response signing key derivation now uses native
hash_hkdf()for RFC 5869 compliance - Key derivation now matches client library (
SecureLicenseClient) exactly - Added missing domain validation to
/activateendpoint (1-255 characters)
Changed
ResponseSigner::deriveCustomerSecret()now useshash_hkdf('sha256', $serverSecret, 32, $licenseKey)- Previous custom HKDF-like implementation was incompatible with client library
Security
- Signatures generated by server now verify correctly with
magdev/wc-licensed-product-client - All three API endpoints now have consistent parameter validation
[0.5.4] - 2026-01-26
Fixed
- REST API
/validateendpoint now returns HTTP 404 forlicense_not_founderror (was 403) - License key validation now enforces minimum 8 characters per API documentation
Added
- Configurable rate limiting via
WC_LICENSE_RATE_LIMITandWC_LICENSE_RATE_WINDOWconstants - Rate limit now defaults to 30 requests per 60 second window (configurable)
Changed
- Improved HTTP status code mapping: 404 for not found, 500 for server errors, 403 for all other errors
- Rate limiting implementation now uses configurable constants instead of hardcoded values
[0.5.3] - 2026-01-26
Added
- Variable licensed product type (
licensed-variable) for selling licenses with different durations - Support for monthly, yearly, quarterly, or lifetime license variations
LicensedVariableProductclass extendingWC_Product_VariableLicensedProductVariationclass for individual variation license settings- Variation-specific license duration settings in product edit page
- Duration labels displayed in checkout domain fields (e.g., "Yearly License")
- Variation ID tracking in order domain meta for proper license generation
Changed
- Updated
LicenseManager::generateLicense()to accept optional variation ID - Checkout now handles variations with separate domain fields per product/variation
- WooCommerce Blocks checkout updated to display variation duration labels
- Store API extension updated to include variation_id in domain data schema
[0.5.2] - 2026-01-26
Added
- Per-license customer secrets for API response verification
- "API Verification Secret" section in customer account licenses page (collapsible)
- Copy button for customer secrets with clipboard support
- Documentation for per-license secret derivation and usage
Security
- Customers no longer need the master server secret for signature verification
- Each license key has a unique derived secret using HKDF-like key derivation
- If one customer's secret is compromised, other customers remain unaffected
Changed
- Updated
ResponseSignerwith static methods for secret derivation - Updated
server-implementation.mdwith per-license secret documentation - Added new translation strings for secret-related UI
[0.5.1] - 2026-01-26
Fixed
- Product versions now sort correctly by version DESC when added via AJAX in admin
- License actions in admin overview are now always visible instead of only on hover
Changed
- Added
compareVersions()JavaScript function for proper semantic version comparison - Updated CSS with
!importantto override WordPress default hover-only behavior for row actions
[0.5.0] - 2026-01-25
Added
- Multi-domain licensing support: Customers can now purchase multiple licenses for different domains in a single order
- Each cart item quantity requires a unique domain at checkout
- New "Enable Multi-Domain Licensing" setting in WooCommerce > Settings > Licensed Products
- Multi-domain checkout UI for WooCommerce Blocks checkout
- DOM injection fallback for checkout domain fields when React component fails to render
- Grouped license display in customer account page by product/order
- "Older versions" collapsible section in customer download area
- Updated email templates to show licenses grouped by product
Changed
- Customer account licenses page now shows licenses grouped by product package
- Order meta now stores
_licensed_product_domainsarray for multi-domain orders - Updated translations with 19 new strings for multi-domain functionality (de_CH)
- Refactored checkout blocks JavaScript to use ExperimentalOrderMeta slot pattern
Technical Details
CheckoutBlocksIntegrationnow usesregisterPluginwithwoocommerce-checkoutscopeStoreApiExtensionhandles both single-domain and multi-domain data formatsCheckoutControllervalidates unique domains per product in multi-domain modeAccountControllergroups licenses by product for package-style display- Backward compatible: existing single-domain orders continue to work
[0.4.0] - 2026-01-24
Added
- Self-licensing prevention: Plugin automatically bypasses license validation when the configured license server URL points to the same WordPress installation
- New
isSelfLicensing()method inPluginLicenseCheckerto detect circular licensing scenarios - New
normalizeDomain()helper method for domain comparison (strips www prefix, lowercases)
Changed
isLicenseValid()andvalidateLicense()now check for self-licensing before attempting validation- Cache clearing now also clears the self-licensing check cache
Technical Details
- Self-licensing detection compares normalized domains of license server URL and current site URL
- Prevents circular dependency where plugin would try to validate against itself
- Plugins can only be validated against the original store from which they were obtained
[0.3.9] - 2026-01-24
Added
- "Generate Licenses" button in order meta box for admin-created orders
- "Generate Missing Licenses" button when some products in an order are missing licenses
- AJAX handler
ajaxGenerateOrderLicenses()for manual license generation from admin - Warning message when order domain is not set before generating licenses
Fixed
- Critical: Licenses are now generated for orders created manually in admin area
- Previously, licenses were only generated via checkout hooks, leaving admin-created orders without licenses
Technical Details
- Added
wclp_generate_order_licensesAJAX action toOrderLicenseController - Updated
order-licenses.jswith generate button handler and page reload on success - Added CSS styles for generate status messages
- Updated translations (365 strings)
[0.3.8] - 2026-01-24
Fixed
- Fixed duplicate German translation string causing
ArgumentCountErrorin settings page - The notification settings description had duplicated text with two
%splaceholders
Changed
- Updated
magdev/wc-licensed-product-clientto latest version (64d215c)
[0.3.7] - 2026-01-24
Added
- Download counter for licensed product versions (tracked per version)
- Download Statistics admin dashboard widget showing total downloads, top products, and top versions
- New
DownloadWidgetControllerclass for download statistics widget - New
incrementDownloadCount(),getTotalDownloadCount(), andgetDownloadStatistics()methods inVersionManager - New
download_countcolumn in product versions database table
Fixed
- Dashboard widget "View All Licenses" link now uses correct page slug (
wc-licenses) - Download links in customer account page no longer result in 404 errors (added query var registration)
- Added
license-downloadendpoint registration during plugin activation
Changed
- Removed redundant "Status Breakdown" section from dashboard widget (info already shown in stat cards)
- License Types section in dashboard widget now uses card style matching the stats row above
- Improved dashboard widget visual consistency
Technical Details
- Added
addDownloadQueryVar()method toDownloadControllerfor proper endpoint registration - Updated
Installer::activate()to registerlicense-downloadendpoint before flushing rewrite rules - Updated translations (356 strings)
[0.3.6] - 2026-01-23
Security
- Added CSRF protection (nonce verification) to CSV export functionality
- Fixed IP header spoofing vulnerability in rate limiting - now requires explicit trusted proxy configuration
- Enabled explicit Twig autoescape for XSS protection
- Fixed unescaped status values in CSS classes in Twig templates
Fixed
- Fixed response signing to use recursive key sorting for client compatibility
- ResponseSigner now recursively sorts nested array keys alphabetically as required by client implementation
Changed
- Rate limiting now only trusts proxy headers when
WC_LICENSE_TRUSTED_PROXIESconstant is defined - Added Cloudflare IP range support via
WC_LICENSE_TRUSTED_PROXIES = 'CLOUDFLARE'configuration - Improved IP detection with CIDR notation support for trusted proxy ranges
Technical Details
- Added
recursiveKeySort()method toResponseSignerfor proper response signing - Added
isTrustedProxy(),isCloudflareIp(), andipMatchesCidr()methods toRestApiController - Twig environment now explicitly sets
autoescape => 'html' - Export CSV link now includes nonce via
wp_nonce_url() - Added
export_csv_url()Twig function for generating export URL with nonce
[0.3.5] - 2026-01-23
Added
- Admin dashboard widget showing license statistics on WordPress dashboard
- Automatic license expiration via daily wp-cron job
- License expired email notification sent when license auto-expires
- New
LicenseExpiredEmailWooCommerce email class (configurable via WooCommerce > Settings > Emails)
Changed
- Improved download list layout in customer account licenses page
- Downloads now displayed in two-row format: file link on first row, metadata on second row
- Better visual separation between download link and version/date/checksum information
Technical Details
- New
DashboardWidgetControllerclass insrc/Admin/for WordPress dashboard widget - Widget displays: total licenses, active, expiring soon, expired counts, status breakdown, license types
- New
LicenseExpiredEmailclass insrc/Email/for expired license notifications - Added
getExpiredActiveLicenses()andautoExpireLicense()methods toLicenseManager - Daily cron now auto-expires licenses with past expiration date and sends notification emails
- Updated
templates/frontend/licenses.html.twigwith new two-row structure - Added
.download-item,.download-row-file,.download-row-metaCSS classes - Improved responsive behavior for download metadata
[0.3.4] - 2026-01-23
Added
- Current version display on single product pages for licensed products
- Version number shown directly under the product title
- Frontend CSS styling for version badge with monospace font
Technical Details
- Added
displayCurrentVersion()method toLicensedProductTypeclass - Hooked to
woocommerce_single_product_summaryat priority 6 (after title) - Added
enqueueFrontendStyles()to load CSS on product pages - Uses
LicensedProduct::get_current_version()to fetch latest version
0.3.3 - 2026-01-22
Fixed
- Fixed version deactivation button not working in admin product versions table
- Corrected parameter order in
updateVersion()call -isActivewas being passed toattachmentIdparameter
Technical Details
- Bug in
VersionAdminController::ajaxToggleVersion()- parameters were in wrong order - Changed from
updateVersion($versionId, null, null, !$currentlyActive)toupdateVersion($versionId, null, !$currentlyActive, null)
0.3.2 - 2026-01-22
Changed
- Updated OpenAPI specification to version 0.3.2
- Added documentation for response signing headers (X-License-Signature, X-License-Timestamp)
- Enhanced API description with response signing security information
Technical Details
- OpenAPI spec now documents optional response signature headers
- Added header component definitions for X-License-Signature and X-License-Timestamp
- All endpoint 200 responses now reference signature headers
- Improved API documentation describing SecureLicenseClient usage
0.3.1 - 2026-01-22
Changed
- Settings page reorganized with sub-tab navigation similar to WooCommerce Advanced tab
- Settings split into three sections: Plugin License, Default Settings, Notifications
- Improved settings UI with WooCommerce-style section navigation
Technical Details
- SettingsController refactored with
getSections()andoutputSections()methods - Section-specific settings methods using PHP 8 match expression
- Hooks updated to use
woocommerce_sections_licensed_productfor sub-navigation
0.3.0 - 2026-01-22
Added
- Self-licensing functionality: Plugin validates its own license against a remote server
- Plugin license settings in WooCommerce > Settings > Licensed Products tab
- License Server URL, License Key, and optional Server Secret configuration
- License status display in settings with verify button
- Localhost bypass: All features work without license when running on localhost
- Admin notice when plugin license is not configured or invalid
Changed
- Frontend features now require a valid plugin license to function
- Disabled features without license: Checkout domain field, customer licenses page, downloads, license generation
Technical Details
- New
PluginLicenseCheckersingleton class for license validation - Integration with
magdev/wc-licensed-product-clientComposer package - Caching: 1 hour for valid license, 5 minutes for errors
- Localhost detection supports: localhost, 127.0.0.1, ::1, and .localhost/.local subdomains
0.2.2 - 2026-01-22
Added
- SHA256 checksum column in admin product versions table
- File hash display in customer account downloads section
- Visual indicators for file integrity verification
Changed
- Checksum file upload field now styled consistently with package upload field
- Download list items now show truncated hash with full hash on hover
Technical Details
- ProductVersion
getFileHash()method now exposed in admin and frontend views - Frontend CSS extended with
.download-hashstyles - Admin CSS extended with
.file-hashstyles
0.2.1 - 2026-01-22
Changed
- SHA256 hash input changed from text field to file upload field
- Checksum files (.sha256 or .txt) can now be uploaded directly
- Improved user experience for version integrity verification
Technical Details
- Added
readChecksumFile()JavaScript function using FileReader API with Promise support - Checksum file format supports both "hash filename" and plain "hash" formats
- Added localized error messages for checksum file validation
0.2.0 - 2026-01-22
Added
- Response signing for REST API using HMAC-SHA256
- SHA256 hash field for product version uploads with checksum validation
- File integrity verification before storing uploaded version files
- New
ResponseSignerclass for automatic API response signing - Database column
file_hashin versions table for storing checksums
Changed
- Version uploads now require file attachments (external URL option removed)
- API responses now include
X-License-SignatureandX-License-Timestampheaders whenWC_LICENSE_SERVER_SECRETis configured
Removed
- External download URL field from product version form
- Direct URL support in version uploads (use Media Library uploads only)
Security
- API response signing prevents tampering and replay attacks
- Per-license key derivation using HKDF-like approach
- SHA256 checksum validation ensures file integrity
Technical Details
- New class:
ResponseSignerfor HMAC-SHA256 response signing - VersionManager extended with
$fileHashparameter and validation - ProductVersion model extended with
fileHashproperty - Signature algorithm:
HMAC-SHA256(derived_key, timestamp + ':' + canonical_json) - Key derivation:
HMAC-SHA256(HMAC-SHA256(license_key, server_secret) + "\x01", server_secret) - Compatible with
magdev/wc-licensed-product-clientSecureLicenseClient
Configuration
To enable response signing, add to wp-config.php:
define('WC_LICENSE_SERVER_SECRET', 'your-secure-random-string-min-32-chars');
0.1.0 - 2026-01-22
Added
- First stable minor release
- Comprehensive code review for WordPress/WooCommerce best practices
- Security audit completed
Changed
- Improved input sanitization for admin page context checks
- Fixed VersionManager null format handling for attachment updates
Technical Details
- All code reviewed for OWASP Top 10 security vulnerabilities
- Verified proper nonce verification, capability checks, and input sanitization
- SQL injection prevention confirmed using
$wpdb->prepare()throughout - XSS prevention confirmed with proper output escaping
- Rate limiting verified on REST API endpoints
- README.md updated with full feature documentation
0.0.11 - 2026-01-22
Added
- Created date column in admin license overview
Technical Details
- Added "Created" column to licenses table in admin (Twig template and PHP fallback)
- Shows when each license was generated
0.0.10 - 2026-01-21
Added
- License meta box on WooCommerce order edit pages
- Editable order domain field with AJAX save
- Editable license domains directly from order page
- View licenses table showing all licenses for an order
- Link to full licenses management page from order view
- Support for both classic orders and HPOS (High-Performance Order Storage)
- Inline editing for license fields (status, expiry date, domain) in admin
- Copy license key button in admin licenses overview
- Live search for licenses in admin overview
- Settings link in plugin actions
Fixed
- Fixed 404 error on licenses menu item
- Fixed Twig template cache issues with auto_reload
Technical Details
- New
OrderLicenseControllerclass for order page integration - New
getLicensesByOrder()method in LicenseManager - New
updateLicenseExpiry()method in LicenseManager - JavaScript file
order-licenses.jsfor inline domain editing - JavaScript file
admin-licenses.jsfor live search and inline editing - AJAX handlers for updating order domain and license domains
- AJAX handlers for inline editing (status, expiry, domain updates)
0.0.9 - 2026-01-21
Added
- API client examples for multiple programming languages
- cURL command examples (
docs/client-examples/curl.sh) - PHP client class (
docs/client-examples/php-client.php) - Python client class (
docs/client-examples/python-client.py) - JavaScript/Node.js client (
docs/client-examples/javascript-client.js) - C# client class (
docs/client-examples/csharp-client.cs) - Client examples documentation (
docs/client-examples/README.md)
Technical Details
- All clients include rate limiting handling (HTTP 429)
- Examples demonstrate validate, status, and activate endpoints
- JavaScript client works in both browser and Node.js environments
- Python client uses dataclasses for type-safe responses
- C# client uses async/await patterns
0.0.8 - 2026-01-21
Changed
- Current version now automatically derived from latest product version
- Email system refactored to use WooCommerce transactional emails
- License expiration warning email now configurable via WooCommerce email settings
Removed
- "Current Version" field from product license settings panel
Technical Details
- New
LicenseExpirationEmailclass extends WC_Email - LicensedProduct's
get_current_version()queries VersionManager - Uses WooCommerce email header/footer templates
- Warning days configurable in plugin settings
0.0.7 - 2026-01-21
Added
- License Dashboard moved to WooCommerce Reports section (Reports > Licenses)
- License search and filtering in admin (by license key, domain, status, product)
- Customer-facing license transfer request with AJAX-based modal
- Email notifications for license expiration warnings (7 days and 1 day before)
- Bulk import licenses from CSV functionality
- Import page with detailed format instructions
- Scheduled cron job for daily expiration checks
Changed
- Dashboard now accessible via WooCommerce > Reports > Licenses tab
- License list page includes search box and filter dropdowns
- Pagination preserves filter state
- Import CSV button added to licenses page header
Technical Details
- AccountController extended with customer transfer AJAX handler and domain normalization
- LicenseEmailController extended with expiration warning scheduling and email templates
- LicenseManager extended with
getLicensesExpiringSoon(),markExpirationNotified(),wasExpirationNotified(),importLicense()methods - AdminController extended with CSV import handling and import page rendering
- Installer clears cron events on plugin deactivation
- Frontend JavaScript extended for transfer modal handling
- Frontend CSS extended with modal and transfer button styles
0.0.6 - 2026-01-21
Added
- License usage statistics/analytics dashboard (WooCommerce > License Dashboard)
- License transfer functionality to change domain from admin
- Export licenses to CSV functionality
- OpenAPI 3.1 specification for REST API documentation (
openapi.json) - Monthly license creation chart on dashboard
- Top products and top domains statistics
- Expiring soon alerts on dashboard
Removed
- API endpoint
/deactivateremoved (license deactivation is now admin-only)
Changed
- Licenses admin page header now includes Export CSV button
- Actions column widened to accommodate Transfer link
- Dashboard link added to licenses page
Technical Details
- New admin page: License Dashboard with statistics overview
- LicenseManager extended with
transferLicense(),getStatistics(),exportLicensesForCsv()methods - AdminController extended with dashboard rendering, CSV export, and transfer handling
- Transfer modal with form for domain change
- REST API now only has three endpoints:
/validate,/status,/activate - OpenAPI 3.1 specification documents all API endpoints with examples
0.0.5 - 2026-01-21
Added
- Bulk license operations in admin (activate, deactivate, revoke, extend, delete)
- License renewal/extension functionality (extend by 30/90/365 days)
- Set license to lifetime (remove expiration)
- Quick action buttons per license row (+30d, ∞, Revoke, Delete)
- Checkbox selection for bulk operations with select-all functionality
- Improved admin notices for bulk operation results
Changed
- Licenses admin page redesigned with WordPress list table styling
- License actions use row-actions pattern for cleaner UI
- Bulk action dropdowns at top and bottom of table (synchronized)
Technical Details
- LicenseManager extended with
extendLicense(),setLicenseLifetime(),bulkUpdateStatus(),bulkDelete(),bulkExtend()methods - AdminController extended with bulk action handling and extend/lifetime actions
- Twig template functions for generating action URLs with nonces
- JavaScript for checkbox sync and bulk action handling
0.0.4 - 2026-01-21
Added
- WooCommerce settings tab "Licensed Products" for default license settings
- Default settings for Max Activations, License Validity, and Bind to Major Version
- Per-product settings now override global defaults (empty = use default)
- Settings link in product edit page pointing to WooCommerce settings
Changed
- Product license settings now show placeholder with default values
- LicensedProduct class now falls back to global defaults when product settings are empty
Technical Details
- New class: SettingsController for WooCommerce settings integration
- LicensedProduct model extended with
has_custom_*methods for checking overrides - Settings stored using WooCommerce options API
0.0.3 - 2026-01-21
Added
- File attachment support for product versions (WordPress Media Library integration)
- Version auto-detection from uploaded filenames (e.g.,
plugin-v1.2.3.zip) - Customer download page for purchased licenses with secure authenticated downloads
- License key copy-to-clipboard functionality on account page and emails
- New card-based UI for customer licenses page with download section
- DownloadController for secure file delivery with hash-based URL verification
Changed
- Product versions meta box now hidden for non-licensed product types (dynamic show/hide)
- Redesigned customer licenses page with modern card layout
- Frontend JavaScript and CSS enhancements for better UX
Technical Details
- New class: DownloadController for secure file downloads
- Database schema updated:
attachment_idcolumn added to versions table - ProductVersion model extended with
getEffectiveDownloadUrl()andgetDownloadFilename() - Secure download URLs use hash verification (license_id-version_id-hash format)
0.0.2 - 2026-01-21
Added
- Product version management UI in admin (meta box on product edit page)
- AJAX-based version CRUD operations (add, delete, toggle active status)
- ProductVersion model and VersionManager for version data handling
- Email notifications with license keys on order completion
- License information included in WooCommerce order completed emails
- Rate limiting for REST API endpoints (30 requests/minute per IP)
- Cloudflare and proxy-aware IP detection for rate limiting
- JavaScript for version management interactions
Changed
- Declared WooCommerce HPOS and cart/checkout blocks compatibility
- Plugin name changed from "WC Licensed Product" to "WooCommerce Licensed Product"
Technical Details
- New classes: ProductVersion, VersionManager, VersionAdminController, LicenseEmailController
- Rate limiting uses WordPress transients for request counting
- HTTP 429 response with Retry-After header when rate limited
0.0.1 - 2026-01-21
Added
- Initial plugin structure with WordPress Plugin API integration
- New WooCommerce product type "Licensed Product" for selling software licenses
- License key generation with format XXXX-XXXX-XXXX-XXXX on order completion
- Domain-based license validation (licenses bound to specific domains)
- REST API endpoints for license management:
POST /wp-json/wc-licensed-product/v1/validate- Validate license for domainPOST /wp-json/wc-licensed-product/v1/status- Check license statusPOST /wp-json/wc-licensed-product/v1/activate- Activate license on domain
- Checkout domain field for licensed products
- Customer account page "Licenses" to view purchased licenses
- Admin interface for license management (WooCommerce > Licenses)
- License settings per product:
- Maximum activations per license
- License validity period (days or lifetime)
- Optional binding to major software version
- Current version tracking
- Custom database tables for licenses and product versions
- Twig template engine integration for views
- Full internationalization support (i18n)
- German (Switzerland, formal) translation (de_CH)
- WooCommerce HPOS compatibility
- Responsive frontend license table
Technical
- PHP 8.3+ required
- WooCommerce 10.0+ required
- PSR-4 autoloading via Composer
- Twig 3.0 template engine
- WordPress REST API integration
- Custom WooCommerce product type extending WC_Product