# LumenCache Changelog

## [1.6.24] - 2026-08-23
### Compatibility
- **WordPress 7.1 Compatibility:** Tested and verified full compatibility with WordPress 7.1.
- **Pre-Bootstrap Drop-in & REST API:** Validated early RAM execution, output buffering lifecycle, surgical purge hooks, and REST API state endpoints under WordPress 7.1.

## [1.6.23] - 2026-08-15
### Security & Hardening
- **Security:** Added explicit `ABSPATH` direct file access prevention guard to `server/lumen-cache-proxy.php` to prevent direct unauthenticated HTTP script execution.
- **Apache Deployer:** Updated `Htaccess::deploy_proxy()` to automatically configure localized `ABSPATH` definitions upon file deployment.

## [1.6.22] - 2026-08-15
### Compliance & UI
- **WordPress.org Compliance:** Full compliance with WordPress.org Guideline 5 (Trialware & Locked Features): removed all locked feature tabs and upsell screens from the free Standard edition.
- **UI:** Added clean external outbound link button "Upgrade to Pro ↗" linking directly to the product page.
- **Drop-in:** `advanced-cache.php` is now completely self-contained with compiled configuration snapshot data.
- **Sanitization:** Added strict input and header sanitization against CRLF injection across all pre-bootstrap request paths.

## [1.6.21] - 2026-08-14
### Housekeeping
- **Metadata:** Updated `Plugin URI` to point to the plugin's own Dev Lab page (`/dev/lumencache/`).

## [1.6.20] - 2026-08-11
### Fixed — UI Layout
- **Quick Setup Tracker:** Updated `.lc-qs-step` and `.lc-qs-step.is-active` flex properties in `assets/css/admin.css` (`flex: 0 0 auto` on non-active steps, `flex: 1 1 220px` on active step) matching Smart Media Redirect Cleaner's CSS layout. Prevents the step connecting lines (`.lc-qs-line`) from overlapping text labels.

## [1.6.19] - 2026-08-11
### Fixed — Pipeline 5: Apache Proxy & .htaccess
- **CRITICAL — `lumen-cache-proxy.php`:** Removed all calls to `sanitize_text_field()` and `wp_unslash()`. This proxy runs before WordPress loads (it is invoked directly by Apache `mod_rewrite`), so WordPress functions do NOT exist. Replaced with native PHP casts.
- **CRITICAL — `lumen-cache-proxy.php`:** All `require __DIR__ . '/index.php'` references were wrong. The proxy is deployed to `wp-content/uploads/`, so `__DIR__` points to the uploads directory — not the WordPress root. WordPress `index.php` is at ABSPATH (two directories up). Fixed by computing `LUMENCACHE_PROXY_ABSPATH = dirname(dirname(__DIR__))` and using it for all WordPress root requires.
- **CRITICAL — `lumen-cache-proxy.php`:** `wp-config.php` lookup used `__DIR__ . '/wp-config.php'` (uploads directory) — wp-config.php is never there. Fixed to use `LUMENCACHE_PROXY_ABSPATH . 'wp-config.php'`.
- **CRITICAL — `lumen-cache-proxy.php`:** `lumen-cache-config.php` lookup used `__DIR__ . '/wp-content/lumen-cache-config.php'` which resolves to `uploads/wp-content/lumen-cache-config.php` — a path that doesn't exist. Fixed to `dirname(__DIR__) . '/lumen-cache-config.php'` (one level up from uploads = wp-content).
- **`class-htaccess.php`:** Full audit — rewrite rule path computation, server detection, deploy/remove logic all verified correct. No additional bugs found.

## [1.6.18] - 2026-08-11
### Fixed — Pipeline 4: Redis Connector
- **Security/Reliability:** `connect_phpredis()` no longer silently ignores `false` return from `$redis->auth()`. A wrong Redis password would previously allow the connection to proceed (all subsequent commands would fail with NOAUTH errors). Now throws `RuntimeException` which is caught by the outer handler, setting `connected=false` cleanly.
- **Reliability:** `connect_phpredis()` now also checks the return value of `$redis->select()` and throws on failure (invalid database index).
- **Code clarity:** Added comment to `connect_predis()` explaining that Predis throws on connection/auth failure (reaching the assignment line already guarantees success).

## [1.6.17] - 2026-08-11
### Fixed — Pipeline 3: Cache Engine
- **Performance:** Debug string concatenation (URI, query string, ob_level) in `start_capture()` and `maybe_write_cache()` was evaluated on every single page request even when `LUMENCACHE_DEBUG` was disabled. Wrapped behind an explicit `LUMENCACHE_DEBUG` guard so production sites pay zero string-building cost.
- **Audit:** All core cache logic (output buffering, cache key building, invalidation hooks, bypass rules, tracking-param stripping) verified correct. No logic bugs found in core flow.

## [1.6.16] - 2026-08-11
### Fixed — Pipeline 2: Drop-in Deployment & Config Write
- **CRITICAL — `advanced-cache.php`:** Removed all calls to `sanitize_text_field()` and `wp_unslash()` which are WordPress functions that do NOT exist when the drop-in executes (it runs before WordPress boots). These caused a PHP Fatal Error on every page load. Replaced with safe native PHP casts and `isset()` checks (e.g. `(string) $_SERVER['REQUEST_URI']`).
- **CRITICAL — `class-drop-in.php`:** Fixed `enable_wp_cache()` Case 1 (WP_CACHE not yet in wp-config.php). The code used `str_replace( $marker, $snippet, $content, $count )` — but `str_replace()` in PHP does not have a 4th count argument. The variable `$count` always remained 0, causing the function to always return `WP_Error` and never actually write `WP_CACHE` to wp-config.php. Fixed using `substr_count()` + `substr_replace()` to correctly detect and insert the define.
- **`advanced-cache.php`:** Bumped internal version to `v1.2.6`.

## [1.6.15] - 2026-08-11
### Fixed — Pipeline 1: Plugin Bootstrap & Lifecycle
- **Lifecycle:** Corrected stale comment in `deactivate()` that incorrectly referred to "ABSPATH" for the proxy file location (proxy was already migrated to uploads dir in 1.6.14).
- **Lifecycle:** `uninstall()` now flushes all Redis cache keys via `Cache_Engine::purge_all()` before removing the plugin, preventing stale HTML from persisting for future plugins.
- **Lifecycle:** `uninstall()` now also deletes `lumencache_pro_status` WP option so Pro licensing state is fully cleaned up on uninstall.
- **Settings:** `effective_connection()` now correctly labels manually-stored TCP settings as `'manual'` instead of `'auto'` — fixes misleading "Auto-detected" source label in the Connection tab for hand-entered host/port settings.

## [1.6.14] - 2026-08-11
### Fixed
- **Repository Cleanup:** Removed `.DS_Store` and `composer.phar` files.
- **Security:** Added direct file access protection via `ABSPATH` check to `server/advanced-cache.php`, `server/lumen-cache-proxy.php`, and `wp-config-example.php`.
- **Security:** Replaced all usages of `unlink()` with `wp_delete_file()` in `includes/class-drop-in.php` and `includes/class-htaccess.php`.
- **File System:** Updated `file_put_contents` in `includes/class-cache-engine.php` and proxy deployment in `includes/class-htaccess.php` to use `wp_upload_dir()` instead of `WP_CONTENT_DIR` and `ABSPATH` to ensure safe, localized writing.
- **Security:** Sanitized all occurrences of `$_SERVER` inputs (`SERVER_SOFTWARE`, `REQUEST_URI`, `REQUEST_METHOD`, `QUERY_STRING`, `HTTP_HOST`, `HTTPS`, `SERVER_PORT`, `HTTP_X_FORWARDED_PROTO`) using `sanitize_text_field( wp_unslash( ... ) )` across multiple files.
- **Security:** Added PHPCS ignore rules to handle valid GET requests that do not require nonces for notice rendering in `class-admin.php` and WooCommerce fragment short-circuiting in `class-woo-guard.php`.
- **Translations:** Added missing `translators:` comments for parameterized strings in `includes/class-admin.php` and `includes/class-rest-api.php`.
- **Naming Conventions:** Prefixed un-prefixed globals and functions in `server/lumen-cache-proxy.php` and `includes/pro-compat.php` with `lumencache_` prefix.
- **Debugging:** Removed active debugging statements (`error_log`) in `includes/class-admin.php` and `includes/class-redis-connector.php`, and replaced `var_export` with string casting in `includes/class-cache-engine.php`.

## [1.6.13] - 2026-08-11
### Fixed
- **Cache Engine:** Prevented WordPress RSS/Atom feeds from being cached to avoid serving feeds with incorrect `Content-Type: text/html` headers. Added `is_feed()` check to `class-cache-engine.php` output buffer bypass conditions.
- **Drop-in Engine:** Applied identical feed bypass checks via URL regex parsing (`/feed/` and `?feed=`) directly in the early `advanced-cache.php` drop-in logic (bumped drop-in version to `v1.2.5`).
- **Security & UI:** Hardened URL sanitization in `handle_flush_url()` within `class-admin.php`. Replaced `sanitize_url()` with `esc_url_raw()` to correctly handle query strings containing ampersands (`&`) without HTML-encoding them into `&#038;`, ensuring exact match during manual single-page cache flushing.
