# Changelog

All notable changes to Maennche Tools 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).

## [2.5.11] - 2026-06-29

### Added

- **Redirect list/delete endpoints:** List and delete redirects. POST-based delete works on hosts that block the `DELETE` method.

## [2.5.10] - 2026-06-29

### Added

- **POST-based page/post delete endpoints:** Added `POST /maennche-tools/v1/pages/{id}/delete` and `POST /maennche-tools/v1/posts/{id}/delete` so Studio can delete content on hosts that block the `DELETE` HTTP method before WordPress receives the request.

### Fixed

- **Trash updates:** `status=trash` is now honored by the shared post/page update sanitizer.
- **Create slugs:** Created posts and pages now derive `post_name` from the title when no slug is supplied.

## [2.5.9] - 2026-06-28

### Added

- **Redirect creation endpoint:** Added `POST /maennche-tools/v1/redirects` using the Redirection wrapper.
- **Authenticated page list endpoint:** Added `GET /maennche-tools/v1/pages` for lean page lists used by Studio AI.

## [2.5.8] - 2026-06-08

### Fixed

- **Mailgun "Your credentials are incorrect." — wrong region endpoint.** Email delivery was failing with a Mailgun 401 even though the API key was valid. Root cause: `Mail_Handler::init_mailgun()` chose the EU vs US Mailgun gateway with `! is_null( getOption('mailgun_region') )`. The "Europe Region" checkbox (no `value` attribute) saves `''` (empty string), **not** `null`, when unchecked — so `is_null()` never matched and every US account was routed to `api.eu.mailgun.net`, where the US domain/key is rejected as "Your credentials are incorrect." Changed the check to `! empty(...)`, matching the checkbox's own render in `views/smtp-config.php`. Verified against the live Mailgun API: the US endpoint sends 200 with the existing key/domain; the EU endpoint returns exactly the 401 that was being logged.

## [2.5.7] - 2026-06-08

### Fixed

- **Email delivery restored (Mailgun SDK bundled).** Mailgun sends on the live site were failing with "Mailgun SDK is not available" / "No PSR-17 url factory found" — contact-form and system emails were not being delivered. Root cause: the Mailgun SDK lives in `includes/extensions/mailgun/vendor/`, which was git-ignored and not packaged, so each plugin-zip update wiped it from the server. Additionally the extension's `composer.json` still pinned the 2.x SDK (`sendMessage()` API, PHP 5.5/7.0 only) while the runtime code was already calling the 4.x API (`->messages()->send()`), and the 4.x SDK requires a PSR-17/PSR-18 implementation via discovery that the old lock never provided.
  - Updated `includes/extensions/mailgun/composer.json` to `mailgun/mailgun-php ^4.0` + `guzzlehttp/guzzle ^7.5` (provides the PSR-18 client and PSR-17 factories) + `php-http/discovery`, pinned to the PHP 8.0 platform.
  - Regenerated the lock and **committed the built `vendor/` so it is bundled in every release zip** — the dependency can no longer be wiped by a plugin update. Verified `Mailgun::create()->messages()` loads with no PSR-17 discovery error.

## [2.5.6] - 2026-06-08

### Fixed

- **Release metadata:** Corrected `readme.txt` `Stable tag`, which had been left at `2.5.1` while the plugin header advanced through 2.5.2–2.5.5, so WordPress reported the wrong version. The header version and the stable tag now agree (2.5.6). This is the packaged release that actually ships the 2.5.4 Tenant Binding hide and the 2.5.5 contact-form `Array to string conversion` fix to production.

## [2.5.5] - 2026-06-07

### Fixed

- **Contact form warning:** Fixed an `Array to string conversion` warning that could surface on the page after submitting a contact form. The mail diagnostic builder in `Mail_Handler` now safely normalizes `to`/`cc`/`bcc`/`ReplyTo` fields (including array-of-array `ReplyTo` values) instead of concatenating them directly, so a failed/queued send can no longer emit a PHP warning to visitors.

## [2.5.4] - 2026-06-07

### Fixed

- **PHP snippet editor:** Unblocked saving in the Scripts PHP snippet editor (previously rejected by client-side validation).
- **Scripts location picker:** Fixed the script-location picker response shape so locations save correctly.
- **Tenant Binding UI (Settings page):** The Settings-page Tenant Binding section is now hidden unless a binding already exists, mirroring the OAuth settings page. The "enter a verification code from Studio" setup flow is a dead end until the Studio-side code-generation UI ships, so it is no longer shown to admins who have no binding.

## [2.5.3] - 2026-06-07

### Fixed

- **Featured image upload:** Featured images from Studio AI content are now pushed to WordPress as base64 JSON instead of multipart, working around Cloudflare blocking multipart uploads.

## [2.5.2] - 2026-06-07

### Changed

- **Featured image transfer:** Featured images are now pushed to WordPress as bytes rather than pulled by URL, improving reliability for AI-published content.
- **Configurable publish author:** The WordPress author used when publishing AI content is now configurable.

### Fixed

- **Tenant Binding UI (OAuth page):** The OAuth settings page now only surfaces the Tenant Binding section when a binding exists, hiding the unusable setup UI otherwise.

## [2.5.1] - 2026-06-06

### Added

- **Media sideload endpoint:** New `/maennche-tools/v1/media` endpoint to sideload media into the WordPress library.

## [2.5.0] - 2026-05-31

### Added

- **WordPress Abilities API:** Maennche Tools operations are now exposed as WordPress Abilities, making the plugin drivable via the MCP Adapter. Includes an ability category and WP-capability permission callbacks for each ability.

### Security

- **Least-privilege hardening:** Tightened the Studio-authenticated user role and added capability/permission guards to the file-management and database controllers.

### Fixed

- **Tenant binding:** Fixed verification-code parsing and corrected the tenant-domain fallback handling in admin settings.

## [2.4.0] - 2026-05-31

### Added

- **Diagnostics tools:** New diagnostics controller/endpoints for inspecting plugin and site health.
- **Page builder support:** Content handlers for Gutenberg, Divi, Elementor, and Beaver Builder so Studio can read/parse builder-based content.
- **MCP enhancements:** Expanded REST surface and `/users/me/` endpoint for MCP-to-plugin integration.

### Fixed

- **Mailgun reliability:** Improved autoloader detection and validation of Mailgun SDK availability; repaired several `Mail_Handler` bugs.
- **PHP 8.4 compatibility:** Fixed `$wpdb->prepare()` array handling and date-handling errors for PHP 8.4.
- **Class loading:** Added missing `use` statements for builder classes in the `yoda_tools` namespace.

## [2.2.1] - 2026-02-04

### Added

- **DELETE endpoints** for posts and pages in plugin REST API (`/maennche-tools/v1/posts/{id}` and `/maennche-tools/v1/pages/{id}`)
- Supports trash (default) and permanent delete via `force` parameter

### Fixed

- **New user role:** Changed from `editor` to `administrator` so Studio-authenticated users have full WordPress access

## [2.1.6] - 2026-02-04

### Fixed

**Critical: Fatal Error on Class Loading**

- **Fixed:** `Class "yoda_tools\Maennche_Tools_Database_Controller" not found` fatal error on sites using database tools
- **Fixed:** `Class "yoda_tools\Maennche_Tools_File_Management_Controller" not found` fatal error on sites using file management
- **Root Cause:** Missing `use` statements in the namespaced `yoda_tools.php` file caused PHP to resolve unqualified class names under the `yoda_tools` namespace instead of finding the global `Maennche_Tools_*` classes
- **Impact:** Any site using Database Controller or File Management features would crash

**PHPStan Bug Fixes (18 real bugs found)**

- **Fixed:** PHPMailer class name case mismatch (`PHPmailer` → `PHPMailer`) in Mail_Handler
- **Fixed:** Missing return values in multiple utility functions
- **Fixed:** Undefined variable `$cron_warnings` in cron tracking
- **Fixed:** `update_option()` autoload parameter type (string `'no'` → bool `false`) in 5 locations
- **Fixed:** `gform_validation` incorrectly registered as action instead of filter in Spam Guard
- **Fixed:** Various undefined variables and redundant null checks

### Added

**Static Analysis & Testing Infrastructure**

- **Added:** PHPStan level 5 with `szepeviktor/phpstan-wordpress` extension
- **Added:** Standalone unit test suite (42 tests) that runs without WordPress installation
- **Added:** CI workflow (GitHub Actions) for PHPStan and unit tests on every push
- **Added:** PHPStan baseline (46 known issues, all noise/optional-dependency related)

### Removed

- **Removed:** Abandoned 2.2.0 folder rename artifacts (`maennche-tools.php`, `migration.php`)

## [2.1.5] - 2026-02-03

### Security

**Spam Guard Fail-Closed Security Fix**

- **Fixed:** Spam Guard now blocks submissions when the API is unreachable (fail-closed) instead of allowing them through (fail-open). This prevents spam from bypassing protection during service interruptions.
- **Added:** Connection timeouts (10s total, 5s connect) to AI spam scoring to prevent forms from hanging indefinitely
- **Scope:** All 5 spam check methods updated: user registration, comments, Contact Form 7, Gravity Forms, login attempts

## [2.1.3] - 2026-01-30

### Fixed

- **Fixed:** Plugin icon not rendering on WordPress update screen. The 20x20 favicon.png was below WordPress's 128px minimum. Added properly sized `icon-128x128.png` (1x) and `icon-256x256.png` (2x) images.
- **Fixed:** "View details" modal showing bare content. Enriched `get_plugin_info()` response with Description, Installation, and Changelog tabs using local plugin data.

## [2.1.2] - 2026-01-30

### Fixed

- **Fixed:** Plugin icon not appearing on WordPress update screen. Upgrader now provides a default icon from local assets when the Studio API doesn't return one.
- **Fixed:** "Clear Update Transients" button reported failure despite working. JS response handler now correctly checks `wp_send_json_success` format.
- **Fixed:** Stale update transient after upgrade could show "update available" for the already-installed version. Transient is now cleared during the upgrade process.

## [2.1.1] - 2026-01-30

### Fixed

- **Fixed:** Encryption key security warning appearing after plugin update. Keys are now generated automatically during version upgrades, not only on activation (deactivate/reactivate cycle no longer required).

### Changed

- **Updated:** Plugin description and feature list in readme.txt to reflect Studio API integration, OAuth 2.0, AI spam detection, and database debug tools added since 2.0.0

## [2.1.0] - 2026-01-30

### Fixed

**Spam Guard API Restored (8-month outage)**

- **Fixed:** Advanced Spam Guard now uses OAuth Bearer token authentication instead of deprecated API key
- **Root Cause:** When OAuth was introduced in v2.0.0, the `advancedSpamGuard` class was never migrated from the deprecated `register` API key class to the new `API_Client` OAuth class. Spam submissions stopped recording in May 2025.
- **Impact:** Form spam detection via Maennche Studio API is fully operational again

**PHP 8.x Null-Safety**

- **Fixed:** `strpos()` deprecation warning on null email in `class-rest-authenticator.php`
- **Fixed:** `str_replace()` on null value in `class-file-management-controller.php`
- **Fixed:** `str_replace()` on null analytics settings in `yoda_tools.php`
- **Fixed:** `trim()` on null query in `class-database-controller.php`

**Test Suite**

- **Fixed:** OAuth classes not loading in PHPUnit test environment after conditional loading optimization
- **Fixed:** Stale test assertions for OAuth authorization URL path and redirect URI format
- **Result:** 52 passing, 0 failures, 5 expected skips

### Improved

**OAuth Conditional Loading**

- **Improved:** OAuth Client and API Client classes now load only when needed (admin pages, REST API requests, or Spam Guard enabled) instead of on every request
- **Improved:** Reduces memory and initialization overhead on frontend page loads

### Added

**Database Debug Features (Maennche Tools MCP Integration)**

- **Added:** Database query endpoint `/maennche-tools/v1/debug/query` for authenticated debugging
- **Added:** Table list endpoint `/maennche-tools/v1/debug/tables`
- **Added:** Schema inspection endpoint `/maennche-tools/v1/debug/schema/{table}`
- **Added:** Admin settings toggle to enable/disable debug features (default: OFF)
- **Added:** Site info now reports `debug_enabled` status

**Security Features:**
- SELECT-only queries (regex validation)
- Sensitive column filtering (user_pass, *_secret, *_key, *_token redacted)
- Rate limiting (10 queries/minute per user)
- Audit logging (last 100 queries tracked in wp_options)
- Admin capability check (manage_options required)
- Opt-in security (debug disabled by default)

**Testing:**
- 57 PHPUnit tests (52 passing, 5 expected skips)
- Covers encryption, security, settings, utilities, OAuth client, API client, database controller

## [2.0.1] - 2025-11-26

### Fixed

**CRITICAL: OAuth Token Auto-Refresh Fix**

- **Fixed:** OAuth tokens now properly auto-refresh after expiration
- **Fixed:** `client_id` is now stored permanently (not just as 1-hour transient)
- **Root Cause:** During initial OAuth connection, the `client_id` was only stored as a temporary transient that expired after 1 hour. When tokens needed to be refreshed later, the `client_id` was unavailable, causing auto-refresh to fail silently.
- **Impact:** Users will no longer see "Not Connected" after 1 hour - tokens will automatically refresh every hour as intended
- **Changes Made:**
  - `client_id` now stored permanently in `yoda_tools_oauth_client_id` option after successful authorization
  - `client_id` properly cleared during disconnect
  - Enhanced error logging throughout token refresh process for better debugging

**Enhanced Diagnostics**

- **Added:** `get_diagnostics()` method to Token Manager for troubleshooting
- **Added:** Comprehensive error logging in token refresh flow
- **Added:** Client ID validation before attempting refresh
- Logs now show: token refresh attempts, missing tokens, API responses, success/failure status

### Technical Details

**Files Modified:**
- `includes/oauth/class-oauth-client.php:246` - Store client_id permanently after token exchange
- `includes/oauth/class-oauth-client.php:288` - Clear client_id during disconnect
- `includes/oauth/class-token-manager.php:135-159` - Enhanced logging in get_access_token()
- `includes/oauth/class-token-manager.php:199-257` - Enhanced logging in refresh_token()
- `includes/oauth/class-token-manager.php:380-401` - Added get_diagnostics() method

**Upgrade Notes:**
- Existing users need to reconnect to Maennche Studio once to store client_id permanently
- After reconnection, auto-refresh will work indefinitely without requiring re-authorization

## [2.0.0] - 2025-11-24

### MAJOR FEATURE: OAuth 2.0 API Integration

This is a major release adding secure OAuth 2.0 integration with Maennche Studio API.

#### Added

**OAuth 2.0 Integration**
- **Added:** Complete OAuth 2.0 Authorization Code flow with PKCE (RFC 7636)
- **Added:** Secure token storage with AES-256-CBC encryption
- **Added:** Automatic token refresh without user intervention
- **Added:** Comprehensive API client for Maennche Studio API
- **Added:** Admin settings page (Yoda Tools → Maennche Studio API)
- **Added:** "Connect to Maennche Studio" OAuth flow
- **Added:** Connection status display with user info and token expiry
- **Added:** Test connection functionality
- **Added:** Disconnect/revoke tokens functionality

**Security**
- ✅ OAuth 2.0 with PKCE - No client secret required
- ✅ AES-256-CBC token encryption at rest
- ✅ CSRF protection via state parameter
- ✅ XSS prevention with proper output escaping
- ✅ Capability checks on all OAuth admin functions
- ✅ Nonce verification for all AJAX requests
- ✅ Input sanitization throughout

**API Client Features**
- **Added:** `yoda_tools()->oauth_api_client` - Access API client from anywhere
- **Added:** GET, POST, PUT, PATCH, DELETE request methods
- **Added:** Automatic authentication header injection
- **Added:** Automatic token refresh on 401 responses
- **Added:** Comprehensive error handling with WP_Error
- **Added:** Convenience methods for conversations, messages, users

**Testing**
- **Added:** 27 PHPUnit tests for OAuth functionality
  - Token encryption/decryption tests
  - PKCE code generation tests
  - OAuth authorization flow tests
  - API request handling tests
  - Integration tests (skipped without real API)
- **All tests passing:** 23 passing, 3 intentionally skipped

**Developer Experience**
- **Added:** OAuth classes in `includes/oauth/` directory
- **Added:** OAuth assets (CSS/JS) for admin interface
- **Added:** Comprehensive inline documentation
- **Added:** Usage examples in admin UI
- **Added:** Public API via `yoda_tools()` singleton

#### Configuration Required

To use OAuth 2.0 integration, add to `wp-config.php`:

```php
// Required
define( 'YODA_TOOLS_OAUTH_CLIENT_ID', 'your-client-id-here' );

// Optional (with defaults)
define( 'YODA_TOOLS_OAUTH_API_BASE_URL', 'https://staging-studio-api.maennche.com' );
define( 'YODA_TOOLS_OAUTH_AUTH_URL', 'https://staging-studio-api.maennche.com/oauth/authorize' );
define( 'YODA_TOOLS_OAUTH_TOKEN_URL', 'https://staging-studio-api.maennche.com/oauth/token' );
```

#### Usage Example

```php
// Get API client
$api = yoda_tools()->oauth_api_client;

// Make API request
$conversations = $api->get_conversations( array( 'limit' => 20 ) );

if ( ! is_wp_error( $conversations ) ) {
    foreach ( $conversations['data'] as $conversation ) {
        echo $conversation['name'];
    }
}
```

#### Technical Details
- **New files:** 9 files (4 OAuth classes, 2 assets, 3 test suites)
- **Lines of code:** ~2,500 lines added
- **Dependencies:** OpenSSL PHP extension (for encryption)
- **WordPress:** Requires WordPress 6.0+
- **PHP:** Requires PHP 7.4+

#### Breaking Changes

**None** - OAuth 2.0 is an additive feature. All existing functionality remains unchanged and compatible.

---

## [1.8.1] - 2025-11-24

### Improvements

#### Code Cleanup
- **Removed:** ~70 lines of dead code including:
  - Commented-out code in autoloader
  - Duplicate `file_exists` checks
  - Deprecated `check_contact_form_seven()` function (64 lines)
- **Improved:** Code maintainability and performance

#### UX Enhancements
- **Improved:** Error message consistency and clarity
  - All error messages now use translation functions for internationalization
  - More specific, actionable error messages with user guidance
  - Examples:
    - "Insufficient permissions" → "You do not have permission to perform this action. Administrator access is required."
    - "Security check failed" → "Security verification failed. Please refresh the page and try again."
    - "No records affected" → "No matching records found. The search text may not exist in your database."
- **Added:** Confirmation dialogs for destructive actions
  - Delete/trash operations now prompt "Are you sure?" confirmation
  - Prevents accidental data loss
  - Applied to all table row actions with "delete" or "trash" in the action slug

#### Testing
- All 13 security and unit tests passing
- Test coverage validates security fixes remain intact

### Technical Details
- Modified files: `settings.php`, `utilities.php`, `autoloader.php`, `advancedSpamGuard.php`
- Lines changed: ~90 lines (70 removed, 20 improved)

## [1.8.0] - 2025-11-24

### SECURITY FIXES (CRITICAL)

This is a major security release addressing 17 vulnerabilities. **Immediate update highly recommended.**

#### High Severity

- **Fixed:** SQL injection vulnerabilities in database replacement tool (`utilities.php`)
  - All 7 database queries now use prepared statements with `$wpdb->prepare()`
  - Proper escaping for LIKE clauses using `$wpdb->esc_like()`
  - Added input validation for empty strings and identical values
- **Fixed:** SQL injection in email log deletion (`utilities.php`)
  - Changed to use `absint()` and prepared statements
- **Removed:** Arbitrary PHP code execution via `eval()` in custom PHP snippets (`settings.php`)
  - Replaced with secure action hook system: `do_action('yoda_tools_custom_php', $post_id, $title, $content)`
  - Added deprecation notice for administrators
  - **BREAKING CHANGE:** See "Breaking Changes" section below
- **Fixed:** Missing capability checks on 9 AJAX handlers
  - All admin-only functions now verify `current_user_can('manage_options')`
  - Prevents unauthorized access to sensitive operations

#### Medium Severity

- **Fixed:** Cross-Site Scripting (XSS) vulnerabilities in admin output
  - Added proper escaping to 6 locations using `esc_html()`, `esc_url()`, `esc_attr()`
  - Table data rendering now properly escapes all user-provided content
- **Secured:** Hardcoded encryption keys moved to constants (`utilities.php`)
  - New constants: `YODA_TOOLS_ENCRYPT_KEY`, `YODA_TOOLS_ENCRYPT_IV`
  - Users can override in `wp-config.php` for better security
  - Maintains backward compatibility with fallback values
- **Fixed:** Insecure Direct Object Reference (IDOR) in email log viewing
  - Added capability verification before displaying email logs
  - Added record existence checks to prevent information disclosure
- **Fixed:** Unsanitized `$_GET` parameter usage in 4 locations
  - All GET parameters now properly sanitized with `sanitize_text_field()`

#### Additional Security Improvements

- **Fixed:** Nonce verification order in 8 AJAX handlers
  - Capability checks now run BEFORE nonce verification (security best practice)
  - Prevents unnecessary nonce generation for unauthorized users
- **Fixed:** Improper `wp_add_inline_script` usage (`yoda_tools.php`)
  - Converted to proper `wp_localize_script()` usage
  - JavaScript nonce now available as `yodaAN.nonce`
- **Added:** Comprehensive input validation to 3 critical functions
  - Post IDs validated with `absint()`
  - Post status/type validated against allowed values
  - Modes validated against whitelisted options

### IMPROVEMENTS

- **Standardized:** AJAX error handling across all endpoints
  - All AJAX handlers now use `wp_send_json_success()` / `wp_send_json_error()`
  - Consistent JSON response format throughout plugin
- **Cleaned:** Removed duplicate code
  - Eliminated 3 duplicate post status registrations in `scripts.php`
  - Reduced code redundancy and improved maintainability

### TESTING

- **Added:** PHPUnit testing infrastructure
  - 15 automated tests covering security-critical functions
  - Unit tests for SQL injection prevention, XSS prevention, capability checks
  - Integration tests for AJAX authorization
  - Test coverage for encryption, input sanitization, and IDOR protection
- **Added:** Testing documentation
  - Complete setup guide in `README-TESTING.md`
  - Quick reference in `QUICK-TEST-REFERENCE.md`
  - Automated setup script `setup-tests.sh`

### BREAKING CHANGES

#### Custom PHP Snippets No Longer Execute via eval()

**What Changed:**
- Custom PHP snippets (post type: `yoda-php`) will **NO LONGER** execute automatically via `eval()`
- This change was necessary to eliminate a critical security vulnerability

**Why This Change:**
- `eval()` execution of user-provided code is an extreme security risk
- Even with admin-only access, it can lead to:
  - Backdoor persistence if admin account is compromised
  - Accidental data loss from coding errors
  - Server compromise
  - Bypassing security plugins

**Migration Path:**

If you are using custom PHP snippets, you must migrate to the new hook-based system:

```php
// OLD WAY (No longer works):
// Creating PHP snippet in admin panel → automatically executed via eval()

// NEW WAY (Required):
// In your theme's functions.php or a custom plugin:
add_action('yoda_tools_custom_php', function($post_id, $title, $content) {
    // Your custom code here
    // Do NOT eval() the $content - implement safe alternatives

    // Example: Execute specific safe functions based on title
    if ($title === 'My Custom Function') {
        // Your safe implementation
    }
}, 10, 3);
```

**For Users:**
- You will see an admin notice explaining this change when viewing PHP snippets
- Existing PHP snippets are preserved but will not execute
- Contact your developer to migrate snippets to the new hook system

### STATISTICS

- **Total Security Fixes:** 17 vulnerabilities eliminated
- **Code Changes:** 30 sections modified across 4 files (~410 lines)
- **Backward Compatibility:** Maintained (except intentional eval() removal)
- **WordPress Coding Standards:** All changes follow WordPress standards
- **PHP Syntax:** All modified files validated with `php -l`

### SECURITY RECOMMENDATIONS

1. **Update immediately** - This release fixes critical vulnerabilities
2. **Custom encryption keys** (optional, recommended):
   ```php
   // Add to wp-config.php for enhanced security:
   define('YODA_TOOLS_ENCRYPT_KEY', 'your-unique-32-char-key-here');
   define('YODA_TOOLS_ENCRYPT_IV', 'your-unique-16-char-iv-here');
   ```
3. **Review PHP snippets** - Migrate any custom PHP snippets to action hooks
4. **Test functionality** - Verify all plugin features work correctly after update
5. **Security scan** - Run a WordPress security plugin scan after updating

### FILES MODIFIED

- `includes/core/settings.php` - 15 sections (~200 lines)
- `includes/core/utilities.php` - 11 sections (~150 lines)
- `yoda_tools.php` - 3 sections (~30 lines)
- `includes/scripts.php` - 1 section (~30 lines)

### ACKNOWLEDGMENTS

Security audit and fixes performed following WordPress security best practices and OWASP guidelines.

---

## [1.7.4] - Previous Release

*Previous changelog entries would go here*

---

## Upgrade Notice

### 1.8.0
CRITICAL SECURITY UPDATE: This release fixes 17 security vulnerabilities including SQL injection, XSS, and arbitrary code execution. Update immediately. Note: Custom PHP snippets will no longer execute via eval() - see changelog for migration instructions.
