Files
2meet-data-optimizer/CHANGELOG.md
T
wpdev fab07655a2 docs(2meet-data-optimizer): 1.2.0 release notes
- Bump to 1.2.0; CHANGELOG / readme entries for PR-066–080, with the post-upgrade ops commands
- ADR-004 Release 2.2 design (scope, drift check / fix / router / resync) and CONTEXT.md drift paragraph
- Verify: composer test, integration, phpcs 0
- PR: PR-086
2026-09-27 09:52:22 +08:00

419 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to this plugin will be documented here.
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
Versioning follows [Semantic Versioning](https://semver.org/).
---
## [1.2.0] — 2026-09-27 — 漂移偵測、範圍收斂、CLI 與診斷(hardening 2.2)
**性質**:功能 + 資料正確性修正。無 schema 變更。延續 ADR-004 的搜尋索引模式;搭配
HivePress AddOn 0.3.0、WooCommerce AddOn 0.2.0。
### Added
- **`wp tmdo drift-check <entity> [--group] [--sample=<n>] [--format]`**(`TMDO_Drift_Check`):
逐 key 比對扁平表與原生 meta 的值(第一筆原生 row → 安全 unserialize →
`Type_Caster::to_db`),回報 miss / diff / extra。序列化 vs JSON、`50` vs `50.000000`
不算漂移;超過 255 字元存 NULL 的 text 不算 miss。結果寫入 `wpdo_drift_status`。(PR-070)
- **`drift-check --fix`**:刪除已刪實體與非本 group post type 的扁平列,其餘漂移列經
`TMDO_Entity_Migration_Engine::migrate_entity()` 從原生重建,清除列快取後再檢查一次。
不寫原生;aeav_only(扁平才是真實資料)一律拒絕。(PR-071、PR-073b)
- **每日抽樣**:`wpdo_daily_health_check` 對 dual_write 以上、非 aeav_only 的 entity 每個
group 抽 500 筆,結果取代既有紀錄。(PR-073)
- **Hook Bus 關閉期間的寫入補回**:entity 從 disabled 進入 dual_write / shadow_read,或
Hook Bus flag 由關轉開時,60 秒後以單次 WP-Cron `tmdo_drift_resync` 執行全量
`drift-check --fix`(不做 `post_modified_gmt` 增量:WooCommerce 直接 SQL 改庫存不會更新
post_modified)。停用 / 解除安裝時清除排程。(PR-074)
- **`wp tmdo bridge-mode <entity> <mode>`**:經 `TMDO_Mode_Manager::set()`,受
Promotion Guard 約束;被拒時 exit 1、模式不變。(PR-069)
- **`wp tmdo member-backfill --all`**:回填所有已註冊的 user group。(PR-068)
- **`wp tmdo cleanup-hp-transients --options [--dry-run|--confirm] [--batch=<n>]`**:
刪除 HivePress AddOn 0.3.0 之前寫進 wp_options 的 `_transient_wpdo_hp_pm_*`(含 timeout),
分批刪除(預設 5000),AddOn 未啟用也可執行。dev36 有 2,314,750 列。(PR-080)
### Changed
- **Post query router 避開漂移中的 group**:上次 drift-check 有 miss / diff / extra 的
group 不路由,整個查詢維持原生(全有或全無);從未檢查的 group 照常路由;aeav_only
不受影響。(PR-072、PR-073b)
- **純排序搜尋 flat-first**:沒有路由篩選的 HivePress `_sort` 搜尋,在該 post type 每篇都有
扁平列時改由扁平表驅動(`STRAIGHT_JOIN` + INNER JOIN);Router 在 `wp_insert_post`
替新文章建空列,覆蓋率以 anti-join 檢查並快取 15 分鐘(隨 post 模式變更失效)。
flat-first 且扁平表是唯一 JOIN 時拿掉 WordPress 為 tax query 加的 `GROUP BY posts.ID`。
dev36 `rating__desc`:原生約 3.3 s、1.1.0 約 1.5–1.9 s、現在約 0.51–0.85 s。(PR-079)
- **Auto-promoter** 的第三個條件改為 `TMDO_Drift_Check::clean_since()`:2 天內每個 group 都
檢查過(抽樣或全量)且沒有漂移;沒有紀錄就不升級。(PR-075)
- **shadow_read diff 節流**:每個 entity type + key 每小時最多記 20 列(疊加既有的
每物件 5 分鐘視窗)。(PR-075)
- **回填 group 改讀 registry**:admin「全部回填」、`post-migrate-group`、`member-backfill`、
`member-audit` 取所有已註冊 group(排除已還原的孤兒 group),不再是寫死清單;含 json
欄位的 group(attachment、nav_menu_item)逐列經 migration engine。(PR-067、PR-068)
- **不再註冊 `post/wc_product`**:WooCommerce 直接讀 product meta、以 SQL 寫庫存,扁平副本
必然漂移(ADR-004 決策 2)。既有的 `wp_wpdo_post_wc_product` 表保留,以
`wp tmdo bridge-restore-native post --group=wc_product --retire` 封存;解除安裝仍會刪除。(PR-077)
- `member-sso-sync`、`member-force-logout` 標示為 deprecated(`sso` group 已不註冊)。(PR-069)
### Fixed
- Entity 回填替沒有原生 row 的 key 寫入 DDL 預設值(`session_count` / `account_flags` = 0),
每個 user 都被捏造出 0;現在寫 NULL,required NOT NULL 欄位保留預設值。(PR-066)
- `member-cutover` 在轉換被拒時 fatal(把 `WP_Error` 當陣列)。(PR-068)
- `doctor` 依 registry 檢查 entity 表(不再因從未註冊的 `sso` 表而每站失敗),並顯示
Promotion Guard 違規與 drift 狀態;`term-comment-diagnose` 依各 filter 的 `is_enabled()`
顯示狀態;`bridge-status` 只計有值的扁平列、eav_ids 限定 group 的 post type
(dev36 wp_core 15306% → 100%)。(PR-076)
- 2.1 稽核:公開 REST route 註明公開理由;admin 23 處三元 echo 依情境 `esc_attr` /
`esc_html`;migration engine 與 health cron 的例外改記 `TMDO_Logger`。(PR-078)
### Docs
- ADR-004「設計(Release 2.2)」、`CONTEXT.md` Entity Bridge 的漂移段落。(PR-086)
### 升級後
- HivePress 站:部署 AddOn 0.3.0 後執行 `wp tmdo cleanup-hp-transients --options --confirm`。
- 曾註冊 wc_product 的站:`wp tmdo bridge-restore-native post --group=wc_product --retire`。
- 已進入 dual_write 以上的站:`wp tmdo drift-check <entity>` 建立第一筆紀錄(未檢查的
group 照常路由)。
---
## [1.1.1] — 2026-09-26 — Security:公開 REST 不再回傳私有欄位
**性質**:安全修正(Critical)。1.0.x 起即存在;1.1.0 zip 已撤回(`dist/withdrawn/`)。
### Security
- **公開的 `GET /wpdo/v1/listings`、`/wpdo/v1/listings/{id}` 會把所有已註冊的 hot / cold
欄位回傳給未登入者**:`TMDO_Schema_Registry::register()` 的 `show_in_rest` 預設為 true,
而 addon 都沒有設定它。dev36 實測可取得 infocards 的 `tmeetic_ig_access_token_enc`、
`tmeetic_ig_token_expiry`、`tmeetic_ig_user_id`,以及 WooCommerce 的 `_purchase_note`。
- `show_in_rest` 預設改為 **false**:要公開的欄位必須明確宣告。
- 受保護的 meta key(底線開頭)與名稱像憑證的 key(token、secret、password、api key、
private key、credential、salt、nonce)即使宣告公開也一律不輸出
(`TMDO_Schema_Registry::rest_exposable()`)。
- Zone A 列表路徑在沒有任何公開欄位時不再回傳整列(fail-closed);篩選參數與 orderby
只接受公開欄位,避免藉由篩選 / 排序推測隱藏值。
- **相容性**:依賴預設公開的欄位,現在需在註冊時加上 `'show_in_rest' => true`,或使用
既有的 `tmdo_rest_listing_visible_fields` filter。
- 測試:`RestApiTest` 新增 3 個;live suite `rest`(未登入 GET 不得出現私有 / 憑證類 key)。
---
## [1.1.0] — 2026-09-26 — HivePress / WooCommerce 搜尋索引模式(hardening 2.1)
**性質**:資料正確性修正 + 查詢改寫補強。無 schema 變更。決策與設計見
`docs/adr-004-search-index-mode-for-hp-wc.md`;搭配 HivePress AddOn 0.2.0。
### Added
- **Promotion Guard**(`TMDO_Promotion_Guard`):HivePress 啟用時 post / user / term /
comment、WooCommerce 啟用時 post / user 不得升到 aeav_only 或執行 cleanup
(`WP_Error( 'promotion_guarded' )`,filter `tmdo_promotion_guard_allow`);已在
aeav_only 的站只顯示後台 notice。(PR-053)
- **`wp tmdo repair-array-literals [--entity] [--confirm]`**:把扁平表中的 `"Array"`
從原生修回;原生也被污染的列出清單。(PR-055)
- **`bridge-restore-native --overwrite / --only-missing`**:預設依模式(aeav_only 覆寫、
其他只補缺);報告新增 `missing` / `differs` / `same` / `default_skipped`。(PR-058)
- **live 測試層** `tests/live/`(在真實站台以 `wp eval-file` 執行):suites
`shadow_write`、`serialized`、`resync`、`router`、`zero_side_effect`,以及 qbench /
fe.sh 等量測工具。(PR-052)
### Changed
- **Hook Bus 寫入順序**:dual_write / shadow_read 由 WordPress 寫原生,扁平表在
`added_ / updated_ / deleted_{type}_meta` 從原生重新同步(含 `delete_all`、
`update_metadata_by_mid` 改 key)。(PR-057)
- **shadow_read** 讀原生,並抽樣比對扁平值(`tmdo_shadow_compare_sample_rate`)。(PR-056)
- **Post query router**:
- 全有或全無:OR、多 post type、含已註冊 key 的巢狀 group、type 語意與欄位不符的
clause 讓整個查詢維持原生;LIKE 包 `%esc_like%`;`pre_get_posts` priority 1000。(PR-060)
- 每個 group 各自 JOIN、不加 GROUP BY;NOT EXISTS 不走狀態 / 日期副本路由。(PR-061)
- meta orderby:HivePress `_sort`(NOT EXISTS + EXISTS)形狀、具名 clause、
`meta_key` + `meta_value_num`。(PR-062)
- routed 搜尋維持 WordPress 的 split query(ID-first)。(PR-062b)
- 依扁平欄位排序且有篩選的搜尋改由扁平表驅動(`STRAIGHT_JOIN`,posts.ID tie-break 改讀等值的
`post_id`),不再以 temporary table 排序;filter `tmdo_router_flat_first` 可關閉。(PR-062c)
- `composer phpcs` 改用 `phpcs.xml`(與 CI 相同)。
### Fixed
- shadow_read 下 `update_*_meta()` 回傳 false、原生沒有寫入(資料遺失)。(PR-056)
- 陣列 / 物件存進 text 欄位變成 `"Array"`;text 超過 255 字元改存 NULL 並記錄
`text_overflow`。(PR-055)
- `bridge-restore-native` 覆蓋較新的原生值(WC 庫存)、替每個 user 捏造預設值列。(PR-058)
- Cold / Hot 表不存在時,`save_post`、`loop_start`、刪除文章仍查詢它們(DB error)。(PR-054、PR-054b)
- 刪除 post / user / term / comment 後,扁平表留下全 NULL 的孤兒列(PR-057 的 NULL 同步會重建已刪的列)。(PR-057b)
- Router:Q05(wp_core 與另一 group 的 key 並用)`Unknown column`;OR / 多 post type /
無 type 數值比較 / 具名 orderby 的結果與原生不同。(PR-060〜062)
### Docs
- ADR-004、`CONTEXT.md` Entity Bridge(寫入順序、shadow_read、搜尋索引模式、Router 規則)、
`docs/BENCHMARK-SCALE.md` 前台與寫入鏈實測。(PR-064)
---
## [1.0.2] — 2026-08-15 — NinjaFirewall 相容性:WAF 設定選項保護
**性質**:防禦性修正 + 文件。無 schema 變更,無破壞性變更。
### Added
- **`docs/WAF-COMPATIBILITY.md`** — NinjaFirewall (WP Edition) 4.9 相容性評估
結論:兩者可共存,**不需要開發 AddOn**(NinjaFirewall 全 codebase 零個
`apply_filters('nfw_*')` / `do_action('nfw_*')`,官方相容手段全在部署層)。
文件涵蓋 WP WAF 與 Full WAF 的模式差異、symlink 多租戶部署的必要設定、
三條開發約束,以及實測風險矩陣。
- **`TMDO_Options_Manager::PROTECTED_OPTIONS`** 常數與註冊守衛
(`modules/options/class-tmdo-options-manager.php`)
`register_settings_group()` 會以 `pre_update_option_{key}` 回傳 `$old_value`,
讓選項不再落地 `wp_options`、改存專屬設定表。但 NinjaFirewall 的 Full WAF 走
`auto_prepend_file`,在 WordPress 載入前就以**原生 mysqli 直查 `wp_options`**
取 `nfw_options` / `nfw_rules`。一旦這些鍵被重導向,WAF 會讀不到設定而
**靜默停止防護 —— 不報錯、不寫 log**。
現以 `PROTECTED_OPTIONS`(`nfw_options` / `nfw_rules` / `nfw_checked`)在註冊
階段擋下,並發出 `_doing_it_wrong()`。守衛置於方法開頭,全部鍵都被擋時提前
返回,不再建立空的設定表。
註:autoload 最佳化不受影響 —— `optimize_autoload()` 只改 `autoload` 欄位、
不刪列,而該處的 `SELECT *` 不看 autoload。
- **`tests/unit/OptionsManagerProtectedTest.php`** — 4 tests / 10 assertions
鎖住「受保護鍵絕不會被掛上 `pre_option_*` / `pre_update_option_*` 攔截」這個
核心保證,並驗證全數受保護時不對資料庫發出查詢。
### Changed
- **Migration Wizard 輪詢間隔 500ms → 2s**(`admin/assets/wpdo-migration-wizard.js`)
原本 2 req/s 打同一個 REST endpoint,容易觸發 WAF 的 rate-limit 與 bot 偵測。
改為 2 秒,與四個 stress-test 面板既有的輪詢節奏一致。
---
## [1.0.1] — 2026-08-08 — Schema Registry 冪等性修正(cold zone 欄位重複累積)
**性質**:核心 bug 修復。無 schema 變更,無 API 變更,無破壞性變更。
### Fixed
- **`TMDO_Schema_Registry::register()` 的 cold zone 分支會無限累積重複項**
(`includes/class-tmdo-schema-registry.php`)
三個 zone 索引的寫入方式並不一致:
- `hot` → `$this->hot_columns[$post_type][$column] = ...`(以 column 為 key,天生冪等)
- `warm` → `$this->warm_fields[$meta_key] = ...`(以 meta_key 為 key,天生冪等)
- `cold` → `$this->cold_fields[$post_type][] = ...`(**append,無去重**)
而 `wpdo_register_fields` 本來就會被觸發多次——核心自身在 `plugins_loaded:4` 觸發,
主檔另有 late-bind safety net 於 `plugins_loaded:30` 再次觸發,好讓在 `:6` 之後才
bootstrap 的 AddOn 也能趕上;再加上主外掛與其 AddOn 可能同時註冊同一批欄位。
**實測影響**:某站台 `cold_fields['hp_vendor']` 累積到 **35 筆但只有 9 個相異值**,
每個 key 重複 4 次。修正後為 9 筆、零重複。
修法:cold 分支加入 `in_array( ..., true )` 去重,使 `register()` 對同一
`(post_type, meta_key)` 成為冪等操作,與 hot / warm 的既有行為一致。
### 驗證
- 核心單元測試 **587 tests / 1156 assertions** 全綠
- `wp wpdo doctor` 於兩個站台皆 0 FAIL
- Version bump 1.0.0 → 1.0.1(2 點一致:header / `TMDO_VERSION`)
---
## [1.0.0] — 2026-07-31 — 取代 wp-data-optimizer v3.4.6
本版把 `wp-data-optimizer` v3.0.1–v3.4.6(92 個 commit)全數 backport 進來,
`wp-data-optimizer` 自此退休:兩個站台皆已停用它,本機目錄改名為
`wp-data-optimizer.retired`,其 git 歷史保留在 gitea。
### 🔒 Security / 正確性
- **7 處 `Logger::error()` 參數不足**(array 傳給 string `$hook`)修正 —— 4 個 stress
tester、auto-promoter、conflict-detector、hook-bus,皆為 TypeError fatal
- **`Logger::trace_id()` 補回**:`Audit_Logger::write_row()` 一直呼叫它,但提煉時漏了;
`Audit_Logger::init()` 從未註冊所以隱藏至今 —— 實機驗證才暴露
- REST 4 個公開端點加上 `show_in_rest` 欄位 allowlist(CVSS 5.3)
- 13 個破壞性 admin 動作由 GET 改 POST + nonce
- DDL 型別白名單(19 型別)、CLI 表名守衛
- 整欄清空改 `wpdo_allow_mass_column_clear` opt-in(原本 >500 列才擋)
- audit 表補 `group_name` / `action` 欄並註冊 `Audit_Logger::init()`
- `known_login_ips` 註冊(spoke-sso 實際寫入的欄位,先前落 `wp_usermeta`)
### ⚡ 並發
- warm 表 `UNIQUE KEY ui_post_meta`(缺它 `ON DUPLICATE KEY UPDATE` 不生效)
- Zone_Cold 改 `JSON_MERGE_PATCH` / `JSON_REMOVE`、Zone_Warm 原子 `increment()`、
hook-bus `write_to_flat` 改 upsert
### 🏗 架構
- 回填 `TMDO_Zone_Router` + `TMDO_Routing_Predicate`(Sync_Bridge 400→269 行)
- 回填 Migration Phase Strategy:interface + base + 11 個 phase 類別,
orchestrator 1107→640 行,公開介面不變
- 核心新增 `TMDO_Standard_Post_Interceptor`,HP AddOn 4 個 interceptor 573→344 行
### 🔌 相容性
- hook 橋改**雙向**:核心一律 `do_action('wpdo_*')`,原本單向轉發使所有
`tmdo_*` 契約收不到事件
- 57 個 AddOn 類別補 `WPDO_*` alias(核心 alias 表在 `plugins_loaded:4` 執行,
涵蓋不到 `:6` 才載入的 AddOn)
- 38 個 CLI 子指令補 `wp tmdo` 命名空間
- 選單 slug 統一回 `wp-data-optimizer`(B 內部 10+ 處連結本來就指向它)
- HP adapter 介面改為 `TMDO_ extends WPDO_`,讓 `instanceof WPDO_HivePress_Adapter` 成立
### 🖥 Admin
- Settings 七個分區各加「儲存此區塊」AJAX 存檔(`wp_ajax_wpdo_save_settings_section`
+ 7 個 `save_section_*()` + `admin/assets/wpdo-settings.js`),整頁送出仍可用
- inline `style=` 由 348 處降到 9 處(剩下的全是 `--wpdo-*` CSS custom property
載體);`wpdo-admin.css` 543 → 912 行,補 149 個 class
### 🚧 邊界
- 核心不再無守衛呼叫 AddOn 類別。`TMDO_Listing_Stats`(HivePress AddOn)先前
在 admin Dashboard、兩個公開 REST 端點、`wp tmdo cleanup --archive-expired`
被直呼,沒裝該 AddOn 的站台會 fatal;`TMDO_HPCT_Import` 在 admin 與
`wp tmdo import-hpct` 同樣缺守衛
- `TMDO_Zone_Warm::VIEW_KEY` / `VIEW_TTL` 由核心持有(值與 AddOn 常數相同的
`'wpdo_views'`,指向同一批列,無資料遷移)
- 新增 `CoreBoundaryTest`:靜態掃描 126 個核心生產檔,強制每處 AddOn 類別
呼叫都在同一函式內有 `class_exists()` 守衛
### ✅ 品質
- 128 個生產檔 `declare(strict_types=1)`
- PHPCS 0 errors / PHPStan level 6(baseline 710)
- 測試:核心 unit 587 / integration 416、hivepress-addon unit 154 /
integration 57、woocommerce-addon unit 10 / integration 18
- gitea CI:核心 6 個 job 全綠 + 11 個 AddOn workflow + branch protection
- 打包 10 項終檢全 PASS(569 KB / 187 entries,schema drift 0:34 CREATE / 34 DROP)
### ⚠️ ABI / 行為變更
- `doctor_callback` 由 3 參數改為 1 參數(表名)
- `wpdo_capture_before_value` 預設 `true` → `false`;需要 `value_before` 的
消費者(audit log)要 `add_filter( 'wpdo_capture_before_value', '__return_true' )`
- `wpdo_allow_mass_column_clear` 現為 opt-in,整欄清空預設被拒
- `SCHEMA_VERSION` 2.0.0 → 2.1.0(audit 表 ALTER)
---
## [0.1.0] — 2026-05-15 (initial release, Phase 0-5 完成)
### Phase 5 hotfix(同日完成)
- 修 `TMDO_WooCommerce::doctor_check()` callback signature mismatch(cli/class-tmdo-cli.php:264 改 call_user_func 傳 3 參數)
- 加 `includes/back-compat/trait-wpdo-anti-eav-aware-alias.php` — trait + interface 反向相容(PHP class_alias 不支援 trait/interface)
- `WPDO_Anti_EAV_Aware` trait wrapper 可讓 2meet-brandcards 等 sister plugin 直接 `use`
- `WPDO_Entity_Adapter_Interface` extends `TMDO_Entity_Adapter_Interface`
- 完整 `uninstall.php`(核心 244 行從 wp-data-optimizer 提煉,34 張表 DROP TABLE 對齊)
- HP AddOn + infocards AddOn `uninstall.php` 補 schema drift check 對齊
- **12 plugin ZIP 全通過 10 終檢**
### 12 ZIP 交付(dist/)
| Plugin | Size | MD5 |
|---|---:|---|
| 2meet-data-optimizer | 521 KB | a10bb191e662cb5fb53a3d23165c71e5 |
| -hivepress-addon | 117 KB | 24bd8c3211421fed86dc551658d7064a |
| -woocommerce-addon | 34 KB | fbd6f60368fc93310f2e90e58c95b53c |
| -spoke-addon | 24 KB | c1e92b755fb1d108a141086ccf1fe519 |
| -hub-addon | 22 KB | 4e010c63ed8ad1dd24f06b8741e3a1b0 |
| -infocards-addon | 22 KB | 7f095fdc4748d3ff4cd4e05f1bf3d417 |
| -latepoint-addon | 21 KB | 60eeb4ea67cdc996cb60b6ad7126f2df |
| -bookings-addon | 21 KB | ac32b85d84e912d3b5a1cdfb56f9fa96 |
| -mobile-bridge-addon | 20 KB | 59905719cfee4bd31967736517391a43 |
| -collab-addon | 20 KB | 1ed0a2983a692a94b6c42f21b62af2c2 |
| -quotation-addon | 20 KB | 5e693a4df3ce48de447cf6277deaece5 |
| -playlist-addon | 20 KB | d52552782f383abbe8f278a5b85cafef |
### CLI smoke test(12 指令 全 PASS)
- `wp tmdo status / doctor / analyze / install / cleanup / health-snapshot / site-metrics / benchmark`
- `wp wpdo status / doctor` (alias 路徑)
- `wp tmdo spoke-sync --dry-run` / `wp tmdo spoke-force-logout --user-id=1 --dry-run`
---
## [0.1.0] — 2026-05-15 (initial release, Phase 0-4 完成)
### Added — 核心反 EAV 引擎(從 wp-data-optimizer v2.16.0 提煉)
- 4 Zone 分流(Hot / Warm / Cold / Archive)+ Sync Bridge 雙寫
- 7 態 FSM 模組生命週期(idle → dual_write → backfill → verify → cutover → cleanup → complete)
- 4 entity 通用引擎(post / user / term / comment)+ Hook Bus + Mode Manager
- Query Router (`pre_get_posts` 改寫) + Query Compiler
- Migration Engine + Orchestrator + Backfill + Stress Tester + Shadow Verifier
- Snapshot / Safety / Diagnostic / Notifications (Email / Slack / Discord / Telegram)
- Crypto AES-256-GCM AEAD + Safe Unserialize
- WP-CLI 18+ subcommand
- Admin Dashboard + KPI Hero + Tab Groups + Setup Wizard + Help Tabs
### Added — 對外向後相容
- `TMDO_*` 類別 + `class_alias` 80+ 個 → 對外保留 `WPDO_*` 類別名
- 8 個常數 alias(`WPDO_VERSION` / `WPDO_PLUGIN_DIR` / `WPDO_TABLE_PREFIX` 等)
- 9 個 hook dual-fire 橋接(`tmdo_register_fields` ↔ `wpdo_register_fields` 等)
- WP-CLI 雙命名空間:`wp tmdo` (主) + `wp wpdo` (alias)
### Removed — 整合層搬出
- HivePress + 12 擴充整合(13 adapter + 7 interceptor + 5 query interceptor + bootstrap + admin + CLI)→ 搬到 `2meet-data-optimizer-hivepress-addon`
- WooCommerce 整合 → `2meet-data-optimizer-woocommerce-addon`
- LatePoint 整合 → `2meet-data-optimizer-latepoint-addon`
- 2meet-infocards / bookings / quotation / mobile-bridge / collab / playlist 整合 → 各自 6 個 AddOn
- Hub-core SSO group 與自訂表註冊 → `2meet-data-optimizer-hub-addon`
- Spoke-sso SSO group 與 CLI → `2meet-data-optimizer-spoke-addon`
- `TMDO_Core::register_hivepress_defaults()` (193 行) → HP AddOn
### Migration from `wp-data-optimizer v2.16.0`
- `wp_wpdo_*` 表結構完全相容(不 rename,新外掛沿用既有 schema)
- 舊外掛先停用即可改用新外掛接管
- 兩外掛**互斥**:本外掛偵測舊外掛仍 active 時會發 admin notice(plan §8.1)
### Limitations / Known issues (Phase 5 follow-up)
- `tests/` 目錄空殼,PHPUnit unit + integration tests 需後續搬遷
- `phpcs.xml.dist` 缺;`composer install --dev` 後可手動跑
- WP 6.5+ `Requires Plugins:` 強制 Plugin Name 比對;hub-core / spoke-sso 仍寫死 `wp-data-optimizer`,需更新或本 plugin 加偽 `Plugin Name: WP Data Optimizer` alias header(Phase 5)
- `TMDO_WooCommerce::doctor_check()` signature 與 Custom_Table_Registry callback 不對齊(warning level)
- Trait `Trait_TMDO_Anti_EAV_Aware` 暫無 alias wrapper(class_alias 不適用 trait)
### Phase 0-4 統計
- **PHP files**: 203(核心 111 + Hub 5 + Spoke 7 + HP 47 + WC 8 + LP 5 + 6 family 各 5)
- **PHP lint**: 全 PASS
- **Plugin active**: 12/12
- **Custom tables registered**: 14(Hub 12 + Spoke 2,未含 6 family no-op)
- **SSO group fields**: 7
- **Schema fields**: 23 (Hot 20 + Cold 3,HP 未安裝 → HP fields no-op)
---
## 來源外掛累計重要 release(供考古)
詳見 `/var/www/Studio/wp-local-dev30/wp-content/plugins/wp-data-optimizer/CHANGELOG.md` 與 `CLAUDE.md`:v2.0.0 → v2.16.0 共 47 次發版的累計改動。
亮點:
- v2.6.4 H-4 加密 webhook 密鑰
- v2.13.3 audit 7/7 finding 全清零
- v2.15.0 AES-256-CBC → AES-256-GCM AEAD
- v2.16.0 UI/UX KPI Hero + Grouped Tab Navigation
---
## [Unreleased]
### Phase 5 候補
- Tests 套件搬遷
- PHPCS 套件 + 0/0 達成
- 打包腳本 10 終檢驗收
- WPDO_ → TMDO_ migration CLI