robotstxt-documentation-mar.../changelog.txt
2026-08-24 11:42:10 +00:00

325 lines
16 KiB
Text

== Changelog ==
= 1.2.2 =
_Release date: 2026-08-24_
**Highlights**
* Manager (by ROBOTSTXT) detection now uses the ecosystem presence constant ROBOTSTXT_MANAGER_NOTICED (Manager 1.6.2+), with a plugin-list scan fallback for older Manager versions
**Changed**
* `robotstxt_docmd_is_manager_active()` now checks the ROBOTSTXT_MANAGER_NOTICED presence constant (Manager 1.6.2+) and falls back to scanning the plugin list (get_plugins() + is_plugin_active()) when the constant is absent; same function name and return type, so callers are unaffected
**Security**
* `composer update` (phpstan 2.2.9, nette/schema 1.3.6 — dev tooling only); `composer audit` clean, no known CVEs
**Compatibility**
* WordPress: 4.2 - 7.1 (floor re-verified with WP-Compat; smoke-tested on 7.2-alpha)
* PHP: 8.0 - 8.5 (floor re-verified with PHPCompatibility 5.6-8.5 full-range scan)
**Translations**
* Spanish (es_ES) and Catalan (ca): verified complete and in sync (156 strings, no changes needed)
**Tests**
* PHP Coding Standards: PHPCS with WordPress-Core, WordPress-Docs, WordPress-Extra — 0 errors
* PHPStan: level 9, 0 errors
* PHPCompatibility: PHP 8.0-8.5 validated (full-range scan 5.6-8.5)
* WP-Compat: WordPress 4.2 floor validated
* PHPUnit: 23 tests pass (17 plugin header tests + 6 new Manager-detection tests covering both detection paths)
= 1.2.1 =
_Release date: 2026-08-17_
**Highlights**
* Automatic updates are now delivered through the Manager (by ROBOTSTXT) plugin; the built-in self-updater has been removed
* A dismissible notice on the Plugins page (and a permanent one on the plugin Settings page) recommends installing Manager when it is not active
* Minimum WordPress lowered to 4.2, the real lowest version the code runs on (verified with WP-Compat)
**Changed**
* Removed the built-in self-updater (`class-robotstxt-updater.php` and `update.json`); updates are now handled by the [Manager (by ROBOTSTXT)](https://www.robotstxt.software/plugins/robotstxt-manager/) plugin
* New admin notice when the Manager plugin is not installed and active: dismissible on the Plugins page, permanent on the plugin Settings page, both linking to the Manager download page
* Minimum WordPress lowered from 6.8 to 4.2 — the real lowest compatible version confirmed by a WP-Compat scan (`wp_delete_file()`, available since WordPress 4.2, is the oldest API used)
* Plugin URI and Update URI now point to https://www.robotstxt.software/plugins/robotstxt-documentation-markdown/
* Author URI updated to https://www.robotstxt.software/
**Security**
* league/commonmark updated from 2.9.0 to 2.10.0 via `composer update` (no known CVEs; `composer audit` clean)
**Compatibility**
* WordPress: 4.2 - 7.1
* PHP: 8.0 - 8.5 (real minimum confirmed by PHPCompatibility 5.6-8.5 full-range scan)
**Translations**
* Spanish (es_ES) and Catalan (ca): 10 strings added that were missing since 1.2.0, plus the new Manager notice string
**Tests**
* PHP Coding Standards: PHPCS with WordPress-Core, WordPress-Docs, WordPress-Extra — 0 errors
* PHPStan: level 9, 0 errors
* PHPCompatibility: PHP 8.0-8.5 validated (full-range scan 5.6-8.5)
* WP-Compat: WordPress 4.2 floor validated
* PHPUnit: plugin header tests pass
= 1.2.0 =
_Release date: 2026-08-07_
**Highlights**
* New: synced post title is taken from the first H1 in the Markdown (and stripped from the body)
* New: repo-relative links are rewritten to the matching WordPress permalink
* New: repository images are sideloaded into the Media Library and referenced by attachment URL
* All deferred findings from the 1.1.1 pre-deploy audit resolved
* GitHub token encryption hardened with HKDF-SHA256 key derivation (with transparent migration of existing tokens)
* CSRF nonce added to the Discover Files "Refresh" action
* Minimum WordPress raised to 6.8; verified compatible with WordPress 7.1; PHP minimum declarations made consistent at 8.0 across all files
**Added**
* **Title from H1:** the synced post title is now taken from the first `# H1` heading in the Markdown (inline formatting stripped to plain text), with the H1 removed from the body to avoid a duplicate heading. Falls back to the filename-derived title when no H1 is present
* **Internal link translation:** repo-relative Markdown links (e.g. `./api.md`, `../README.md`) are rewritten to the permalink of the matching mapped WordPress content. External, `mailto:`, and anchor links are left untouched; links with no matching mapping keep their original URL
* **Repository image sideloading:** images referenced in the Markdown are downloaded from the repository, added to the Media Library, and their references replaced with the attachment URL. Already-imported images are reused on subsequent syncs (tracked per post); removed images are kept in the Media Library (non-destructive)
**Security**
* Patched CVE-2026-71478 (and advisory GHSA-2q4p-g7hv-5rgv) in league/commonmark — an unsafe-link filter bypass that could defeat `allow_unsafe_links: false`. Updated league/commonmark 2.8.2 → 2.9.0
* GitHub token encryption now derives its AES-256 key with HKDF-SHA256 from `wp_salt('auth')` instead of using the salt directly; existing tokens are migrated transparently to the new `v2:` format on first decrypt (covers the cron path too)
* Discover Files "Refresh from GitHub" action is now nonce-protected — previously a crafted link could force an unrequested GitHub API call (CSRF)
* GitHub API request paths are now `rawurlencode()`d (defensive hardening)
* Sideloaded images are validated by extension (jpg, jpeg, png, gif, webp) and size (< 10 MB) before storage; SVG is intentionally excluded
**Fixed**
* "Using cached data / fetching fresh data" indicator on Discover Files now reflects reality — it always showed "cached" because the cache was tested after being populated
* `target_post_type` is now validated against registered public post types on save, falling back to `page`
* Debug action dispatch refactored into a single `switch`, each case retaining its `check_admin_referer()` check, to reduce the chance of a missing nonce check
**Changed**
* Inline `onclick` confirm on Delete replaced with a `data-confirm` attribute + delegated handler (CSP-friendlier, less fragile)
* Add Mapping "existing content" dropdown now queries only public post types (excludes attachments and the internal mapping CPT) with `no_found_rows` for better performance on large sites
**Compatibility**
* WordPress: 6.8 - 7.1
* PHP: 8.0 - 8.5
* MariaDB: 11.4 or newer
**Developer**
* Added `bin/preflight.sh` — automated pre-deploy gate (PHPCS, PHPStan 9, PHPCompatibility, PHPUnit, `composer audit`, candidate-ZIP inspection); PASS/FAIL report per section, never invokes `deploy.sh`
* Added `.claude/settings.json` deny rules (`deploy.sh`, `git push/tag/merge`) enforcing the AGENTS.md operating boundaries mechanically
* `composer.json` `require-dev` completed and pinned: added `dealerdirect/phpcodesniffer-composer-installer` + `phpcsstandards/phpcsutils`; pinned `squizlabs/php_codesniffer` and `johnbillion/wp-compat`
* Patched two high-severity CVEs in dev tooling (not shipped — `deploy.sh` uses `--no-dev`): `squizlabs/php_codesniffer` 3.13.5 → 3.13.6 (CVE-2026-67434), `wp-coding-standards/wpcs` 3.3.0 → 3.4.1 (CVE-2026-45293). `composer audit` fully clean
**Tests**
* PHP Coding Standards: PHPCS with WordPress-Core, WordPress-Docs, WordPress-Extra — 0 errors
* PHPStan: level 9, 0 errors
* PHPCompatibility: PHP 8.0-8.5 validated
* PHPUnit: plugin header tests pass
* Manual testing: WordPress 7.1
= 1.1.1 =
_Release date: 2026-06-08_
**Highlights**
* Security hardening: CommonMark raw HTML passthrough disabled, encrypted token no longer autoloaded, HMAC now uses `wp_json_encode()` instead of `serialize()`
* Bug fix: admin notices now visible for all operations (sync, create, update, delete, errors)
* Infrastructure: full dev tooling added (PHPCS, PHPStan, PHPUnit, deploy script)
* Real PHP minimum corrected to 8.0 (confirmed by PHPCompatibility 10.x scan)
**Security**
* CommonMark: disabled raw HTML passthrough (`html_input: strip`, `allow_unsafe_links: false`) — prevents stored XSS if an upstream repository is compromised
* Settings option now stored with `autoload = false` — encrypted GitHub token no longer loaded on every WordPress request (defense in depth)
* Replaced `serialize()` with `wp_json_encode()` in updater HMAC cache (eliminates PHPCS object-injection warning)
* Added strict base64 length validation before IV extraction in `robotstxt_docmd_decrypt_token()`
* Added `base64_decode()` strict return-value check in `robotstxt_docmd_get_file_content()`
**Fixed**
* Admin notices now display results for all operations: mapping created, mapping updated, mapping deleted, sync complete, and error messages — previously only "Settings saved" was shown
* `wp_update_post()` return value now checked during sync — silent post-update failures were previously reported as success
* Wrong textdomain `'robotstxt-smtp'` in updater class corrected to `'robotstxt-documentation-markdown'`
**Changed**
* `robotstxt-updater.php` renamed to `class-robotstxt-updater.php` (WordPress file-naming convention)
* Minimum PHP version header corrected from 8.2 to 8.0 (real minimum confirmed by PHPCompatibility 10.0.0-alpha2 scan — union types, `str_starts_with()`, `str_contains()`, and `mixed` type are the binding constraints)
**Developer**
* Added `composer.json` with full require-dev tooling (PHPCS, PHPStan 2.x, PHPUnit 9.6, PHPCompatibility 10.0.0-alpha2, wp-compat, yoast/phpunit-polyfills)
* Added `phpstan.neon` (level 9), `.phpcs.xml` (WordPress-Core/Docs/Extra), `bin/deploy.sh`, `phpunit.xml.dist`
* PHPUnit: 17 plugin header tests added (`tests/PluginHeadersTest.php`)
* Added `docs/known-issues.md` and `docs/db-migrations.md`
* `class-robotstxt-updater.php`: PHPCS 0 errors, PHPStan level 9 0 errors (full compliance)
**Compatibility**
* WordPress: 6.7 - 7.1
* PHP: 8.0 - 8.5
* MariaDB: 11.4 or newer
**Tests**
* PHP Coding Standards: PHPCS 3.x with WordPress-Core, WordPress-Docs, WordPress-Extra — 0 errors, 0 warnings
* WordPress Coding Standards: WPCS 3.3.0
* PHPStan: level 9, 0 errors (szepeviktor/phpstan-wordpress 2.0.3)
* PHPCompatibility: 10.0.0-alpha2 — PHP 8.0-8.5 validated
* PHPUnit: 17/17 tests pass (plugin header tests)
* Manual testing: WordPress 7.0, 7.1
= 1.1.0 =
_Release date: 2026-03-28_
**Highlights**
* Editor-level access: editors can now manage documentation mappings without administrator privileges
* Full PHPStan level 9 compliance — zero errors across all plugin files
* Security patch for two CVEs in league/commonmark
* `target_order` (menu_order) field fully implemented end-to-end
**Security**
* Patched CVE-2026-33347 and CVE-2026-30838 by upgrading league/commonmark to 2.8.2
**Changed**
* Access level changed from `manage_options` (administrator) to `edit_pages` (editor) across all admin pages, form handlers, and debug functions
* `robotstxt_docmd_debug_run_cron()` now has a typed `int $mapping_id` parameter
**Fixed**
* PHPStan level 9: replaced all implicit `mixed` casts with proper type-narrowing via `is_string()`, `is_int()`, and `is_numeric()` guards
* New `robotstxt_docmd_input_string()` and `robotstxt_docmd_input_int()` helpers used for all superglobal (`$_POST`, `$_GET`) access
* `MappingData` and `MappingInput` global type aliases defined in `phpstan.neon` — file-level `@phpstan-type` aliases do not propagate between files in PHPStan 2.x procedural code
* `target_order` field was rendered in the form UI but never saved to post meta or applied during sync — now fully implemented
* `openssl_decrypt()` false return properly handled in token decryption
* `get_edit_post_link()` null return handled safely in debug run-cron output
* Redundant `isset()` guards removed on statically-typed array shapes
* Uninstall handler narrows `get_option()` mixed return before array access
* `size_format()` false return handled in discover-page file list
* Settings and debug functions use `is_array()` narrowing on `get_option()` before accessing keys
* `json_decode()` results in GitHub debug functions fully type-narrowed before key access
**Developer Features**
* PHPStan level 9: 0 errors (down from 104 in v1.0.0)
* `phpstan.neon` now includes global `MappingData` and `MappingInput` type aliases
* `robotstxt-updater.php` moved to `bootstrapFiles` in PHPStan config to avoid strict analysis of shared utility
* `$default` parameter renamed to `$fallback` in helpers (reserved keyword warning)
* Short ternary (`?:`) replaced with explicit `false !==` check (PHPCS rule)
**Compatibility**
* WordPress: 6.7 - 7.0
* PHP: 8.2 - 8.4 (verified on PHP 8.4.x)
* MariaDB: 10.6 or newer
**Dependencies**
* `league/commonmark`: 2.8.0 → 2.8.2 (security patch)
* `eduardovillao/wp-since`: 1.3.0 → 1.4.0
* `phpunit/phpunit` held at ^10.5 (v13.x available; pending test suite migration)
* `squizlabs/php_codesniffer` held at ^3.13 (v4.x available; pending WPCS 4.x confirmation)
**Tests**
* PHP Coding Standards: PHPCS 3.x with WordPress-Extra ruleset — 0 errors, 0 warnings
* WordPress Coding Standards: WPCS 3.3
* PHPStan: level 9, 0 errors (szepeviktor/phpstan-wordpress extension)
* PHPCompatibility: PHP 8.2 - 8.4 validated
* Manual testing: WordPress 6.8, 7.0
= 1.0.0 =
_Release date: 2026-01-26_
**Highlights**
* Initial release of Documentation Markdown plugin
* Automatic synchronization of Markdown files from GitHub to WordPress
* Full support for GitHub Flavored Markdown
* Encrypted GitHub token storage
* Flexible mapping system for multiple repositories
**Added**
* Core synchronization functionality between GitHub and WordPress
* Automatic scheduled sync (hourly, twice daily, daily)
* Manual on-demand sync via admin interface
* Markdown to HTML conversion using CommonMark (league/commonmark)
* Flexible file-to-content mapping system
* Custom Post Type (robotstxt_map) for mapping management
* Encrypted GitHub token storage (AES-256-CBC)
* Full internationalization support (i18n/l10n ready)
* Multi-repository support
* Clean admin interface with status badges
* Support for pages, posts, and custom post types as sync targets
* Configurable post author and parent page
* Page order (menu_order) support
* Debug tools for troubleshooting (visible when WP_DEBUG enabled)
* Cron job management and repair tools
* Clean uninstall with optional data deletion
* Settings page for GitHub configuration
* Mappings management interface (list, add, edit, delete)
* Sync status monitoring with timestamps
* Rate limiting awareness for GitHub API
* Cache system using WordPress Transients API
**Security**
* All user input sanitized using WordPress functions
* All output escaped (esc_html, esc_attr, esc_url)
* Nonce verification on all forms and actions
* Capability checks for all admin actions (manage_options — changed to edit_pages in 1.1.0)
* Prepared statements for all database queries
* GitHub tokens encrypted at rest using AES-256-CBC
* OWASP Top 10 mitigation implemented
* Direct access prevention on all PHP files
* CSRF protection on all state-changing operations
* XSS prevention through proper escaping
* SQL injection prevention through prepared statements
**Developer Features**
* Procedural PHP architecture following KISS principles
* PHP 8.2+ modern features (typed parameters, match expressions)
* Complete PHPDoc documentation on all functions
* WordPress Coding Standards (WPCS) compliant
* PHPCS/WPBF validated (0 errors, 0 warnings)
* Extensible architecture with WordPress hooks
* Clean, well-documented codebase
* Composer-based dependency management
* Production-optimized deployment script (bin/deploy.sh)
**Compatibility**
* WordPress: 6.7 - 6.9
* PHP: 8.2 - 8.5
* MariaDB: 10.6 or newer
**Tests**
* PHP Coding Standards: PHPCS 3.x with WordPress-Extra ruleset
* WordPress Coding Standards: WPCS 3.3
* PHPCompatibility: PHP 8.2 - 8.5 validated
* Security Audit: Complete OWASP Top 10 coverage
* Manual testing: WordPress 6.7, 6.8, 6.9