# License-Client for WooCommerce Licensed Product Plugin **Author:** Marco Graetsch **Author URL:** **Author Email:** **Repository URL:** **Issues URL:** **Package-Name:** `magdev/wc-licensed-product-client` ## Project Overview This composer package implements a Client for the WooCommerce Licensed Product Plugin. It uses the REST API as described in `tmp/openapi.json` to activate, validate and check the status of licenses. ## Features - Easy integration in licensed software packages - Defines a PHP constant if a licensed is valid or not - Obfuscate the security critical code parts using plain PHP tools as best as possible ### Key Fact: 100% AI-Generated This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase was created through AI assistance. ## Temporary Roadmap **Note for AI Assistants:** Clean this section after the specific features are done or new releases are made. Effective changes are tracked in `CHANGELOG.md`. Do not add completed versions here - document them in the Session History section at the end of this file. ### Known Bugs No known bugs at the moment ### Version 0.2.0 No changes at the moment. ## Technical Stack - **Language:** PHP 8.3.x - **PHP-Standards:** PSR-3, PSR-4, PSR-6, PSR-18 - **Coding-Style:** Symfony - **HTTP-Client-Library:** symfony/http-client - **Dependency Management:** Composer - **OpenAPI Description:** `tmp/openapi.json` --- **For AI Assistants:** When starting a new session on this project: 1. Read this CLAUDE.md file first 2. Semantic versioning follows the `MAJOR.MINOR.BUGFIX` pattern 3. Check git log for recent changes 4. Verify you're on the `dev` branch before making changes 5. Run `composer install` if vendor/ is missing 6. Test changes before committing 7. Follow commit message format with Claude Code attribution 8. Update this session history section with learnings 9. Always update the `README.md` on related changes 10. Keep changes in a single `CHANGELOG.md` 11. Follow markdown linting rules (see below) Always refer to this document when starting work on this project. ### Markdown Linting Rules When editing CLAUDE.md or other markdown files, follow these rules to avoid linting errors: 1. **MD031 - Blank lines around fenced code blocks**: Always add a blank line before and after fenced code blocks, even when they follow list items. Example of correct format: - **Item label**: (blank line here) \`\`\`php code example \`\`\` (blank line here) 2. **MD056 - Table column count**: Table separators must have matching column counts and proper spacing. Use consistent dash lengths that match column header widths. 3. **MD009 - No trailing spaces**: Remove trailing whitespace from lines 4. **MD012 - No multiple consecutive blank lines**: Use only single blank lines between sections 5. **MD040 - Fenced code blocks should have a language specified**: Always add a language identifier to code blocks (e.g., `txt`, `bash`, `php`). For shortcode examples, use `txt`. 6. **MD032 - Lists should be surrounded by blank lines**: Add a blank line before AND after list blocks, including after bold labels like `**Attributes:**`. 7. **MD034 - Bare URLs**: Wrap URLs in angle brackets (e.g., ``) or use markdown link syntax `[text](url)`. 8. **Author section formatting**: Use a heading (`### Name`) instead of bold (`**Name**`) for the author name to maintain consistent document structure. --- ## Session History ### 2026-01-22 - Version 0.0.1 **Completed:** - Initialized composer project of type `library` - Configured package metadata (name, description, license, author) - Set up PSR-4 autoloading for `Magdev\WcLicensedProductClient` namespace - Added symfony/http-client ^7.0 as HTTP client dependency - Created project structure (src/, tests/) - Added README.md, CHANGELOG.md, and .gitignore - Initialized git repository on `dev` branch - Pushed initial commit to origin **Learnings:** - OpenAPI spec (tmp/openapi.json) defines 3 POST endpoints: `/validate`, `/status`, `/activate` - API base path: `{baseUrl}/wp-json/wc-licensed-product/v1` - Git remote configured via SSH: `ssh://git@src.bundespruefstelle.ch:2022/magdev/wc-licensed-product-client.git` ### 2026-01-22 - Version 0.1.0 **Completed:** - Created `LicenseClientInterface` as public API contract - Implemented `LicenseClient` with PSR-3 logging and PSR-6 caching support - Added DTO classes: `LicenseInfo`, `LicenseStatus`, `ActivationResult` - Added `LicenseState` enum for license status values (active, inactive, expired, revoked) - Created comprehensive exception hierarchy (10 exception classes) - Added PSR dependencies: `psr/log` ^3.0, `psr/cache` ^3.0, `psr/http-client` ^1.0 - Updated README with usage examples for basic usage, logging, caching, and exception handling - Merged dev to main branch **Learnings:** - Architecture follows separation: Interface (public API) → Client (implementation) → DTOs (data) → Exceptions (errors) - Cache keys use SHA256 hashes of license keys to avoid exposing sensitive data - `LicenseClient` designed for obfuscation: all sensitive logic contained in single class - Symfony HttpClient works well with PSR interfaces via `symfony/http-client-contracts` - Keep a Changelog format allows duplicate headings per version (MD024 warning can be ignored) ### 2026-01-22 - Version 0.1.0 (Security Layer) **Completed:** - Added PHPUnit ^11.0 test framework with 66 tests total - Implemented `SecureLicenseClient` with response signature verification - Created `ResponseSignature` class for HMAC-SHA256 signing/verification - Created `StringEncoder` for XOR-based string obfuscation - Created `IntegrityChecker` for source file hash verification - Added `SignatureException` and `IntegrityException` for security errors - Documented server-side implementation in `docs/server-implementation.md` - Merged all changes to main branch **Learnings:** - Response signature verification (HMAC) is more secure than code obfuscation alone - Per-license key derivation prevents cross-license signature reuse - Timestamp validation (5-minute tolerance) prevents replay attacks - Server must sign responses with matching algorithm for client verification - IntegrityChecker normalizes line endings for cross-platform hash consistency - StringEncoder uses XOR with expanded key for simple obfuscation (not encryption) - PHPUnit 11 uses PHP 8 attributes (`#[Test]`, `#[CoversClass]`) instead of annotations - OpenAPI spec (tmp/openapi.json) updated to v0.3.2 with signature header definitions ### 2026-01-23 - Client Documentation **Completed:** - Created comprehensive `docs/client-implementation.md` documentation - Documented all classes: LicenseClient, SecureLicenseClient, DTOs, Exceptions, Security classes - Added integration guides for: Basic PHP, WordPress plugins, Laravel, Symfony - Documented constructor parameters, method signatures, and return types - Added complete exception hierarchy reference with error codes - Included best practices section for production use - Added API reference with endpoints and request/response formats - Added troubleshooting section for common issues - Updated README.md with documentation links section **Learnings:** - Client documentation complements server documentation for complete integration guide - Integration examples for major PHP frameworks help adoption - Error code mapping to exception classes aids programmatic error handling ### 2026-01-24 - Security Audit and Fixes **Completed:** - Performed comprehensive security audit of entire codebase - Fixed JSON encoding error handling in `ResponseSignature::buildSignaturePayload()` - Sanitized exception messages in both client classes to prevent information disclosure - Fixed header normalization to treat empty values as null in `SecureLicenseClient` - Added SSRF protection with URL validation and private IP range blocking - Replaced custom key derivation with RFC 5869 compliant `hash_hkdf()` - Added input validation in all DTO `fromArray()` methods - Added DateTime exception handling in DTOs to prevent uncaught exceptions - Added new `allowInsecureHttp` constructor parameter for development environments **Learnings:** - Security audit identified 7 fixable issues across critical, high, and medium priority - `hash_hkdf()` is PHP's native RFC 5869 implementation - prefer it over custom HKDF - SSRF protection requires: URL scheme validation, private IP blocking, DNS resolution checks - Exception messages should never expose internal details to end users - DTO validation should check both existence (`isset`) and type (`is_int`, `is_bool`, etc.) - Empty header values should be treated as missing (null) not empty strings - Constructor parameters added: `allowInsecureHttp` for HTTP on non-localhost in dev mode - Private IP ranges to block: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16, 0.0.0.0/8