=== 2meet Data Optimizer ===
Contributors: 2meetio
Tags: performance, database, postmeta, optimization, hivepress
Requires at least: 6.0
Tested up to: 6.9
Requires PHP: 8.1
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Four-zone postmeta optimization for WordPress. Migrates wp_postmeta to dedicated custom tables (Hot/Warm/Cold/Archive) for dramatically faster queries.

== Description ==

**2meet Data Optimizer** replaces the slow, generic `wp_postmeta` EAV table with four purpose-built storage zones, each optimized for a specific access pattern:

| Zone | Name | Best For | Speed Gain |
|------|------|----------|-----------|
| A | Hot | Search / filter fields (price, category, status) | 3–12× faster |
| B | Warm | TTL counters (view counts, temporary flags) | N/A |
| C | Cold | Display / description fields (JSON blob + Object Cache) | 2–4× faster |
| D | Archive | Expired data (gzip compressed, restorable) | N/A |

= Key Features =

* **Zero-downtime migration** — 7-state machine (idle → dual_write → backfill → verify → cutover → cleanup → complete) with rollback support
* **Fully replaces HP Custom Tables (HPCT)** — one-command import of all HPCT flags and migration records
* **HivePress integration** — automatic field detection for hp_listing, hp_vendor, and 17+ HivePress extensions
* **LatePoint integration** — booking meta interception
* **WooCommerce Orders interception** — order meta routing
* **MySQL / MariaDB + SQLite dual-engine** — works with both the standard MySQL stack and the SQLite drop-in
* **REST API** — `/wp-json/wpdo/v1/` endpoints for listings, stats, and status monitoring
* **WP-CLI** — 13 commands: status, install, doctor, analyze, migrate, verify, cutover, rollback, enable, disable, import-hpct, benchmark, cleanup
* **Rate limiting** — IP transient + cookie-based dedup for POST /view; Admin Dashboard shows Top 10 rate-limited posts
* **Object Cache integration** — Zone C bulk prefetch on `loop_start` + `save_post` cache warming
* **Admin Dashboard** — 4-group 20-tab UI: Dashboard / Zones / Migration / Classifier / Entity Bridge / User-Term-Comment-Post migration wizards / Stress Testers / Logs / HPCT Import / REST API / HivePress / Settings
* **Zone Classifier** — analyzes existing postmeta and suggests optimal zone placement (transient-cached, 1h TTL)
* **Multisite** — auto-installs tables on new site creation
* **i18n ready** — `.pot` template + Traditional Chinese (zh_TW) 100% complete

= Real-World Performance (MariaDB 11.8.2, n=200) =

* **hp_listing single-field read**: ~633ms → ~56ms = **12× faster** (Zone A benchmark)
* **hp_vendor single-field read**: ~334ms → ~108ms = **3.1× faster** (Zone A benchmark)
* **hp_vendor JSON blob read**: ~270ms → ~87ms = **3.1× faster** (Zone C benchmark)
* **Query Router T2 full-row get_row**: **28.1× faster**
* **Query Router T7 multi-field write set_many**: **95.3× faster**

= Requirements =

* WordPress 6.0+
* PHP 8.1+
* MySQL 5.7+ / MariaDB 10.4+ (or SQLite via drop-in)

== Installation ==

1. Upload the `2meet-data-optimizer` folder to `/wp-content/plugins/`
2. Activate the plugin through the **Plugins** screen in WordPress
3. Navigate to **2meet Data Optimizer** in the admin menu
4. Run `wp tmdo doctor` (WP-CLI) or click **Run Doctor** in the Dashboard tab to verify installation
5. Use `wp tmdo analyze {post_type}` to see zone placement recommendations
6. Use `wp tmdo migrate {module}` to start migrating a module

= Migrating from HP Custom Tables =

1. Keep HP Custom Tables active
2. Run `wp tmdo import-hpct` to copy all HPCT state
3. Verify with `wp tmdo doctor`
4. Deactivate HP Custom Tables

== Frequently Asked Questions ==

= Will my data be lost if I deactivate the plugin? =

No. During the `dual_write` and `backfill` phases, all data continues to be written to `wp_postmeta`. Data in Zone tables is only the primary source after `cutover`. You can `rollback` any module before reaching `complete` state.

= Does this work without WP-CLI? =

Yes. All migration operations are available through the Admin UI under **2meet Data Optimizer → Migration**. WP-CLI is optional but recommended for batch operations.

= Is SQLite supported? =

Yes. The plugin automatically detects the SQLite drop-in (`WP_SQLite_DB` / `WP_SQLite_Translator`) and applies compatibility patches. Zone D gzip archive and Zone A flat columns both work on SQLite.

= Will this conflict with HivePress or HP Custom Tables? =

2meet Data Optimizer loads at `plugins_loaded` priority 4 (before HPCT at priority 5) and includes compatibility logic to prevent duplicate hook registration. Running alongside HPCT is fully supported during the transition period.

= How do I roll back a migration? =

```
wp tmdo rollback {module}
```

This reverts to `dual_write` state. All reads return to `wp_postmeta` immediately. You can re-attempt the migration at any time.

= What is the Zone Classifier? =

The Classifier tab analyzes your existing `wp_postmeta` data (access frequency, value cardinality, field length) and suggests which zone each meta key belongs in. Results are cached for 1 hour per post type.

== Screenshots ==

1. Dashboard — overview of all modules, test counts, and rate-limit statistics
2. Migration — 7-state progress bar per module with migrate/verify/cutover/rollback actions
3. Zone Classifier — postmeta analysis with zone recommendations
4. REST API Tab — endpoint documentation with cURL examples and JavaScript SDK

== Changelog ==

= 1.0.0 =
* Supersedes `wp-data-optimizer` v3.4.6 — that plugin is retired; this one is the single unified engine
* Version numbering restarts at 1.0.0; entries below 3.4.6 are the predecessor's history, kept for archaeology
* Security: 7 × Logger::error() arity fatals fixed; REST field allowlist; 13 destructive admin actions moved GET → POST; DDL type whitelist; mass column clear is now opt-in via `wpdo_allow_mass_column_clear`
* Concurrency: warm table UNIQUE KEY, JSON_MERGE_PATCH / JSON_REMOVE cold writes, atomic Zone_Warm::increment()
* Architecture: TMDO_Zone_Router + TMDO_Routing_Predicate, Migration Phase Strategy (11 phase classes), TMDO_Standard_Post_Interceptor
* Compat: bidirectional `wpdo_*` ⇄ `tmdo_*` hook bridge, 57 AddOn class aliases, `wp tmdo` namespace for all 38 CLI subcommands
* ABI: `doctor_callback` is now 1-arg; `wpdo_capture_before_value` defaults to false
* Integration layers (HivePress / WooCommerce / LatePoint / 2meet-*) live in 11 separate AddOn plugins

= 3.3.2 =
* Tests: 21 new unit tests for Diagnose, Install_Schema, Backfill_Bulk, Backfill_Unserialize, Verify_Sample migration phases (609 total, 0 failures)
* New: TMDO_Crypto::is_key_derivable() public helper; wp tmdo doctor [WARN] when AUTH_KEY/SECURE_AUTH_SALT absent
* Fix: phpcs:disable file-level suppressors reduced 37 → 19 via phpcs.xml directory-level exclude-pattern rules
* Docs: README.md + readme.txt Stable tag aligned to v3.3.1 in prior release; CHANGELOG.md backfilled for v3.1.5–v3.3.1

= 3.3.1 =
* Security: 13 admin GET state-changing operations converted to POST form (nonce-protected) — prevents nonce leakage via Referer header (CVSS 4.3)
* Security: REST endpoints pre-filter Zone A/C fields via show_in_rest registry (CVSS 5.3)
* Fix: phpcs:disable file-level suppressors reduced from 37 to 19 — directory-level exclusions in phpcs.xml replace broad per-file disables
* Fix: TMDO_Crypto::is_key_derivable() public helper; wp tmdo doctor reports WARN when AUTH_KEY/SECURE_AUTH_SALT absent
* Tests: 21 new unit tests for Diagnose, Install_Schema, Backfill_Bulk, Backfill_Unserialize, Verify_Sample phases

= 3.3.0 =
* Refactor: TMDO_Migration_Orchestrator removes final; 18 self::ENTITY_TYPE → static::ENTITY_TYPE for late-static-binding subclass override
* Tests: HookBusIntegrationTest (14 tests) covers intercept_update/get/delete against real MariaDB; tearDownAfterClass clears Schema_Manager table_exists cache

= 3.2.0 =
* Quality: declare(strict_types=1) added to all 181 production PHP files (includes/, admin/, cli/)

= 3.1.9 =
* CI: PHPCS step in test.yml is now a blocking gate (removed || true); release.yml requires full test-gate (lint + phpcs + unit + integration) before publishing
* Security: wp tmdo doctor adds HTTP accessibility probe for backup directory; nginx snippet surfaced when dir returns 200

= 3.1.8 =
* Security: M-AUTH-1 fix — draft/private/trash posts return 403 to anonymous users in REST get_listing; regression test added
* Fix: TMDO_Conflict_Monitor catch block surfaces errors via TMDO_Logger::warning instead of swallowing silently
* Docs: ADR-001 (post entity source-of-truth contract); ADR-002 (dual_write naming conflict between FSM and Entity Bridge)
* Tests: Migration Phase unit tests for Cleanup RuntimeException guards + 4-phase lifecycle; Mode_Manager cache stubs in bootstrap

= 3.1.7 =
* Perf: Zone Cold save_blob() refactored from 2-query SELECT+INSERT/UPDATE to single INSERT...ON DUPLICATE KEY UPDATE (TMDO_DB::upsert)
* Fix: TMDO_DB::upsert() MySQL branch migrated from deprecated VALUES() to row-alias syntax (INSERT ... AS new_vals ON DUPLICATE KEY UPDATE col = new_vals.col)
* Fix: Same row-alias migration for points_manager, term_comment_misc_bucket, hivepress requests/messages adapters
* Docs: README.md version updated to 3.1.7; Admin UI section updated to reflect 4-group 20-tab layout
* Docs: readme.txt Stable tag updated to 3.1.7; changelogs added for v3.0.1–v3.1.6

= 3.1.6 =
* Fixed: TMDO_Logger::error() call-site arity — all catch-block callers updated to 3-argument form (module, hook, message)
* Fixed: WP_DATA_OPTIMIZER_VERSION constant now delegates to TMDO_VERSION instead of hardcoded '3.0.0'
* New: Gitea CI now runs 477 integration tests against MariaDB 11.4 on every push
* New: release.yml requires test-gate before publishing a GitHub/Gitea release
* Perf: TMDO_DB::upsert() MySQL branch migrated from deprecated VALUES() to row-alias syntax (MySQL 8.0.20+ / MariaDB 10.3.3+)
* Perf: Zone Warm set() refactored to single-query upsert; new atomic increment() method
* Perf: Zone Cold save_blob() refactored from 2-query select+insert/update to single upsert
* Perf: TMDO_Schema_Manager::table_exists() caches results per request to avoid repeated SHOW TABLES
* Perf: cache_orchestrator L1 eviction O(n) → O(1); ORDER BY RAND() eliminated from verify()
* Security: wpdo_rest_listing_visible_fields filter for field-level REST exposure control
* Security: wpdo_allow_mass_column_clear filter gates delete_all (default false)
* Security: TMDO_Crypto derived_key() returns empty string when salts absent; encrypt/decrypt short-circuit safely
* Chore: phpunit.xml failOnWarning=true; composer.json production classmap autoload

= 3.1.5 =
* Security: Gitea release.yml rewritten — release job now requires test-gate (unit + lint) to pass first
* Chore: capture_before_value filter default changed false to eliminate 2 extra DB queries per managed write

= 3.1.4 =
* New: User EAV ratio optimization — admin_prefs group +14 WP admin UI keys; commerce group +3 WC runtime stats; hp_user group +hp_verified
* Perf: dev10 ratio improved 1:1.73 → 1:1.42; dev20 1:2.09 → 1:1.07; dev21 (Dokan Pro 1.8M vendors) 1:1.00

= 3.1.3 =
* Fixed: Last hardcoded inline style removed (conflict-detector.php → wpdo-list-disc class)
* New: scripts/install-local-dev.sh rsync deployment script
* Improved: .wpdo-mode-badge CSS transition added

= 3.1.2 =
* Fixed: ci-package.sh now uses rsync staging so ZIP top-level directory is correct 2meet-data-optimizer/
* Fixed: phpunit-integration.xml excluded from ZIP

= 3.1.1 =
* Fixed: Version header alignment (3.1.0 → 3.1.1) and Gitea DB_PASS secret for integration tests

= 3.1.0 =
* New: scripts/ci-package.sh + .gitea/workflows/release.yml (push v* tag → auto-package + Gitea release)

= 3.0.3 =
* Fixed: wp tmdo doctor partner plugin doctor_callback invocation (call_user_func($cb) → call_user_func($cb, $tbl_raw)); eliminates WooCommerce "Too few arguments" warnings

= 3.0.2 =
* UX: 18 admin files — all inline style= replaced with CSS utility classes
* New: Settings tab split into 7 independent save-section cards with AJAX save
* New: wpdo-admin.css +36 utility classes

= 3.0.1 =
* Architecture: Strategy + Template Method + Zone Router + Partner Registry patterns
* New: 11 injectable Migration Phase objects; TMDO_Standard_Post_Interceptor abstract base; TMDO_Zone_Router dispatch layer
* Fixed: PHPCS 0 errors / 0 warnings project-wide

= 3.0.0 =
* New: HivePress family integration covering 13 official addons (core / blocks / bookings / favorites / marketplace / memberships / messages / requests / reviews / seo / social-links / statistics / tags). Auto-detect, zero overhead when HivePress absent.
* New: 6-command CLI namespace `wp tmdo hivepress {detect,score,doctor,migrate,rollback,benchmark}`.
* New: REST endpoints `GET /wpdo/v1/hivepress/{status,score,health}` (manage_options gated, read-only).
* New: Admin tab `Tools → 2meet Data Optimizer → HivePress 整合`.
* New: 8-dimension anti-EAV suitability scorer with per-adapter + aggregate reporting.
* New: Comment query router (rewrites hp_message recipient lookup, hp_favorite UNIQUE check, etc. — feature flag gated).
* New: Cron optimizer replacing HivePress hourly listing-expiry full scan (feature flag gated).
* New: Conflict guard against legacy hp-custom-tables / hp-info-cards plugins.
* Schema: 8 new zone/shadow tables (hot_hp_request, hot_hp_membership[_plan], hot_hp_booking, comment_hp_{message,favorite,offer}, term_hp_listing_tag).
* Refactor: legacy `class-tmdo-hivepress.php` (242 lines) re-cast as deprecated stub delegating to new core adapter.
* Tests: +144 unit tests + 7 integration tests; full suite 1013 tests / 2469 assertions / 0 failures.
* Security: SQL injection / XSS / capability / ABSPATH guards all audited PASS.

= 2.6.10 =
* Fixed: 壓力測試「取消」無法中斷 — 原本 cancel() 寫入的 cancelled status 會被 in-flight run_batch() 結尾的 update_option() 覆寫回 running（race condition）
* Added: `CANCEL_FLAG` transient — cancel() / cleanup() 設旗標；run_batch() 開頭、run_batch_realistic() 每個 user 迭代之前都檢查；read-modify-write 結尾保留 cancelled status
* Added: 前端 cancel 按鈕點擊立即 UI 反饋（disabled + 「取消中…」），避免使用者再點一次

= 2.6.9 =
* Fixed: 啟動壓力測試 504 Gateway Timeout — `start()` 不再同步執行 batch（之前 batch=500 + realistic mode 會塞 30 分鐘以上）
* Added: `BATCH_DEADLINE_SEC=8s` wall-clock 上限 — 每個 pump batch 跑滿 8 秒就 yield，下一次 polling 接手；遠低於 nginx 60s timeout
* Added: PHP `set_time_limit()` 在 pump 內動態設定，確保 batch 有足夠時間完成
* Improved: Realistic mode 預設批次提示 — 前端偵測 batch>10 時提示確認（每 user ~3 秒，batch>10 撞 deadline）
* Improved: Admin UI 啟動後立即顯示進度卡片，不必等第一次 polling

= 2.6.8 =
* Fixed: 壓力測試進度條不更新 — 不再依賴 wp-cron 自動觸發；`get_progress()` 內建 pump 機制，每次 polling 主動推進一個 batch（用 transient lock 防併發）
* Fixed: 啟動測試後立刻同步執行第一個 batch，使用者第一次 polling 即可看到進度
* Fixed: `finalize()` 完成時清除殘留 cron event
* Fixed: 兩種模式 (fast / realistic) 端到端驗證 — 進度即時推進、Hook Bus 正確攔截、密碼 PassWord2026! 可登入

= 2.6.7 =
* Added: User Entity 壓力測試 + Benchmark 工具（Tools → 2meet Data Optimizer → 壓力測試）— 設定要建立的測試使用者數，一鍵自動填滿所有 user 相關 flat tables（hot/cold/membership/activity/profile/sso/points_ledger）
* Added: 兩種寫入模式 — `fast`（直接 bulk INSERT，~5-10K users/秒）/ `realistic`（走 wp_insert_user + Hook Bus，測試生產路徑）
* Added: 完整 Benchmark 報告 — 寫入速率 / 批次延遲 / DB 容量（每張表 data_length + index_length）/ 6 種查詢效能（含原生 EAV baseline 對比）
* Added: WP Cron 驅動的批次任務 + 即時進度條（2 秒 polling，顯示 users/sec、ETA、PHP peak memory）
* Added: REST API — `/wpdo/v1/stress-test/{status|start|cancel|cleanup|benchmark}`（皆需 manage_options）
* Added: Admin 新 Tab「壓力測試」附警告 banner，一鍵清除所有 test_* 使用者及其 flat table 資料

= 2.6.6 =
* Added: Entity Bridge tab in admin (Tools → 2meet Data Optimizer → Entity Bridge) with health cards per entity (user/term/comment) — shows mode, pipeline visualization, per-group coverage bars, shadow diff count, auto-promote status, and guided recommendation
* Added: Async cron-driven Backfill engine (migrate_group_batch) — REST POST /entity-bridge/backfill triggers WP Cron, self-reschedules every 5 s until all EAV rows are migrated to flat table
* Added: REST API endpoints (requires manage_options) — GET/POST /wpdo/v1/entity-bridge/health, /backfill, /promote, /demote
* Added: TMDO_Entity_Health class — aggregates coverage pct, migration checkpoint, shadow diffs, auto-promote eligibility per entity
* Added: wpdo-entity-bridge.js — real-time polling (5 s) during active backfill, inline promote/demote with confirmation dialogs
* Verified: 356 unit / 181 integration / 0 failures; PHPCS 0 errors / 0 warnings

= 2.6.5 =
* Security: A-4 cleanup — removed all plaintext id_token persistence from Spoke (update_user_meta _tmso_last_id_token writes removed); logout now calls delete_user_meta to progressively clean stale values
* Fixed: Integration test isolation — ZoneHotIntegrationTest, ZoneWarmIntegrationTest, WarmArchiveIntegrationTest, SyncBridgeIntegrationTest setUpBeforeClass() now uses DROP TABLE IF EXISTS + CREATE TABLE to guarantee clean schema even after interrupted prior runs; eliminates 65 spurious failures
* Verified: 356 unit / 181 integration / 0 failures; PHPCS 0/0; stress-tested with pre-polluted tables

= 2.6.4 =
* Security: H-4 — AES-256-CBC encryption for Slack/Discord/Telegram webhook secrets via new TMDO_Crypto class; key derived from AUTH_KEY + SECURE_AUTH_SALT; stored as enc:v1:<base64(iv|ciphertext)>; backward-compat with existing plaintext values
* Security: A-4 — SLO hash migration: Hub stores sha256(id_token) per user+client on token issuance; /oauth/logout accepts id_token_hash_hint with hash_equals() timing-safe comparison; Spoke prefers hash path with legacy JWT fallback
* Admin: webhook inputs use type=password + autocomplete=new-password; empty submission preserves existing encrypted value

= 2.6.3 =
* Security: H-1/H-2 — TMDO_Snapshot_Reader::apply() verifies sha256+size before executing SQL; is_safe_name() enforces $wpdb->prefix
* Security: H-3/M-2 — wpdo_rl_stats capped at 100 entries to prevent unbounded wp_options growth
* Security: M-3 — nginx backup-directory protection notice in admin + README-NGINX.txt with location block
* Security: L-1 — TMDO_DB::table() sanitizes input with sanitize_key()

= 2.6.2 =
* Added: wp tmdo benchmark --custom-tables flag benchmarks all 117 registered custom tables
* Added: TMDO_Site_Metrics_Collector — daily 05:00 UTC cron writes 11 site-wide metrics to wpdo_site_metrics (90-day retention)
* Added: wp tmdo site-metrics CLI command with --collect, --history, --days, --format options

= 2.6.1 =
* Added: E2E test suite T-A01–T-A20 (21 tests): Snapshots tab, Setup Wizard 5-step, Export health+snapshots

= 2.6.0 =
* Added: wp tmdo doctor integrates Custom Table Registry — partner tables shown by provider with status/row-count/doctor_callback
* Added: wp tmdo bridge-status shows dual_write progress: flat table rows vs EAV distinct IDs, progress_%

= 1.3.31 =
* Fixed: PHP WASM / WP Playground compatibility — merged multiple PHP tags on line 604 of admin class to avoid Parse error in PHP WASM 8.3

= 1.3.30 =
* Added: Zone A covering indexes — TMDO_Installer::add_covering_indexes() auto-generates compound indexes based on column types
* Added: WP-CLI wp tmdo add-indexes — applies covering indexes to existing hot tables as an upgrade path
* Added: EXPLAIN-verified index usage: hp_featured+price filter scans 52 rows vs 477 full table scan
* Benchmark: hp_listing Zone A 3.6x, Zone B 3.6x, Zone C 2.4x (n=200, MariaDB 11.8.2)

= 1.3.29 =
* Fixed: WordPress Coding Standards (WPCS) — zero violations (phpcs exit 0)
* Fixed: All output properly escaped with esc_html(); REMOTE_ADDR sanitized with wp_unslash() + sanitize_text_field()
* Fixed: PreparedSQL phpcs:ignore annotations for validated table names; Yoda conditions corrected
* Added: phpcs.xml ruleset; complete docblocks (@param/@return/@var/@throws) across all classes
* Verified: 291 tests / 492 assertions / 0 failures (PHP 8.1–8.3, MariaDB 10.11–11.4)

= 1.3.28 =
* Added: `readme.txt` for WordPress.org submission (Description, Installation, FAQ, Changelog, Screenshots)
* Verified: 291 tests / 492 assertions / 0 failures (PHP 8.1–8.3, MariaDB 10.11–11.4)

= 1.3.27 =
* Added: SyncBridgeTest (14 unit tests) — full guard condition coverage for intercept_get/update/add/cleanup_post
* Added: CacheLayerTest (9 unit tests) — prefetch(), warm_post(), get_stats() coverage
* Added: Admin Dashboard rate-limit stats card — total 429 events, Top 10 rate-limited posts, reset button (nonce-protected)
* Performance: Zone A hp_vendor n=200: 2.5×; Zone C hp_vendor n=200: 3.1×

= 1.3.26 =
* Added: ZoneArchiveTest (20 unit tests) — archive, archive_batch, get with gzip decompression, restore, delete, stats
* Added: Unit test coverage for RestApi (+5), ZoneCold (+3), ZoneHot (+2), ZoneWarm (+3)
* Added: Cookie-based dedup for POST /view rate limiting (Set-Cookie header, SameSite=Strict)
* Added: Rate-limit stats tracking (wpdo_rl_stats option) in get_status() response
* Added: CLI benchmark — Zone B (Warm) and Zone C (Cold) support added to `wp tmdo benchmark`

= 1.3.25 =
* Added: ZoneHotIntegrationTest, ZoneWarmIntegrationTest (MariaDB), SyncBridgeIntegrationTest, QueryRouterIntegrationTest
* Added: CI GitHub Actions workflow — PHP 8.1/8.2/8.3 × MariaDB 10.11/11.4 with TZ: UTC
* Added: Zone C integration tests (ZoneColdIntegrationTest, 15 tests)
* Added: REST API rate limiting (IP transient, 1 hit/IP/post/hour, HTTP 429)
* Performance: Zone A hp_listing benchmark n=200: 12×; hp_vendor: 3.1×

== Upgrade Notice ==

= 1.3.31 =
Bug fix for PHP WASM / WP Playground environments. Recommended for all users.

= 1.3.30 =
Adds covering indexes for Zone A hot tables. Run `wp tmdo add-indexes` on existing installations to apply. Required for optimal multi-field filter performance.

= 1.3.29 =
WPCS compliance release — zero phpcs violations. Security hardening (escape, sanitize). Upgrade recommended before WordPress.org submission.

= 1.3.28 =
Maintenance release — WordPress.org submission preparation. No functional changes.

= 1.3.27 =
Adds Admin Dashboard rate-limit statistics card. Upgrade recommended for sites using the POST /view endpoint.
