# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [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()` and `outputSections()` methods - Section-specific settings methods using PHP 8 match expression - Hooks updated to use `woocommerce_sections_licensed_product` for 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 `PluginLicenseChecker` singleton class for license validation - Integration with `magdev/wc-licensed-product-client` Composer 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-hash` styles - Admin CSS extended with `.file-hash` styles ## [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 `ResponseSigner` class for automatic API response signing - Database column `file_hash` in versions table for storing checksums ### Changed - Version uploads now require file attachments (external URL option removed) - API responses now include `X-License-Signature` and `X-License-Timestamp` headers when `WC_LICENSE_SERVER_SECRET` is 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: `ResponseSigner` for HMAC-SHA256 response signing - VersionManager extended with `$fileHash` parameter and validation - ProductVersion model extended with `fileHash` property - 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-client` SecureLicenseClient ### Configuration To enable response signing, add to `wp-config.php`: ```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 `OrderLicenseController` class for order page integration - New `getLicensesByOrder()` method in LicenseManager - New `updateLicenseExpiry()` method in LicenseManager - JavaScript file `order-licenses.js` for inline domain editing - JavaScript file `admin-licenses.js` for 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 `LicenseExpirationEmail` class 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 `/deactivate` removed (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_id` column added to versions table - ProductVersion model extended with `getEffectiveDownloadUrl()` and `getDownloadFilename()` - 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 domain - `POST /wp-json/wc-licensed-product/v1/status` - Check license status - `POST /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 [Unreleased]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.3.1...HEAD [0.3.1]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.3.0...v0.3.1 [0.3.0]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.2.2...v0.3.0 [0.2.2]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.2.1...v0.2.2 [0.2.1]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.2.0...v0.2.1 [0.2.0]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.1.0...v0.2.0 [0.1.0]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.11...v0.1.0 [0.0.11]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.10...v0.0.11 [0.0.10]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.9...v0.0.10 [0.0.9]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.8...v0.0.9 [0.0.8]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.7...v0.0.8 [0.0.7]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.6...v0.0.7 [0.0.6]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.5...v0.0.6 [0.0.5]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.4...v0.0.5 [0.0.4]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.3...v0.0.4 [0.0.3]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.2...v0.0.3 [0.0.2]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.1...v0.0.2 [0.0.1]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/releases/tag/v0.0.1