=== 一介資男(Mxp.TW) 開發工具箱 ===
Contributors: mxp
Donate link: https://mxp.tw/lw
Tags: development, snippets, database, migration, security
Requires at least: 5.5
Requires PHP: 7.4
Tested up to: 7.1
Stable tag: 3.6.20
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

WordPress 開發與維運工具箱，整合外掛安裝、資料庫維護、搬站輔助、安全片段、站點管理與前端問題回報。

== Description ==

一介資男(Mxp.TW) 開發工具箱不是單一功能外掛，而是一個 WordPress 開發、維運、搬站與站點管理工具包。套件內含主要工具箱與四個可獨立啟用的子外掛，讓管理員只啟用目前站台需要的能力。
整套外掛最低支援 WordPress 5.5 與 PHP 7.4；各項第三方整合仍須同時符合該第三方外掛版本本身的最低環境需求。


= 套件架構 =

* `Dev Tools - Mxp.TW`：主要工具箱。提供外掛/主題安裝、打包、取代、資料庫維護、網站設定檢視與檔案異動檢查。
* `Dev Tools: Snippets - Mxp.TW`：常用維運片段。集中處理安全強化、登入/後台調整、媒體上傳政策、報告排程與網域到期檢查。
* `Dev Tools: Site Manager - Mxp.TW`：多站管理輔助。匯出/匯入站台資訊，並以 passkey、加密 token 與 HMAC 提供跨站快速登入。
* `Dev Tools: Hide Login Page - Mxp.TW`：登入路徑防護。將預設登入入口改為自訂路徑，並把原始登入與未登入後台入口導向 404。
* `Dev Tools: Feedback Reporter - Mxp.TW`：登入用戶全站問題回報。前台與後台可擷取目前頁面、錄製短片、標註截圖、填寫描述後由本站安全轉送 webhook。

= Dev Tools - Mxp.TW（主要工具箱） =

主要工具箱面向高權限管理員與開發者，功能集中在「安裝、搬站、檢查、替換」：

* 開發常用外掛清單：從遠端清單與 WordPress.org API 取得外掛資訊，支援安裝、更新與啟用。
* Themeforest List：輸入 Envato 或 MXP 授權碼後，列出可下載的主題、外掛與其他檔案，並支援線上安裝。
* 外掛搜尋工具：在後台嵌入作者整理的外掛搜尋介面，從可信來源帶回下載連結後安裝。
* 外掛/主題打包：可從外掛列表、主題工具、最近異動檔案、`wp-content` 或 `wp-config.php` 產生 ZIP 下載。
* 外掛/主題取代：上傳 ZIP 後解析外掛或主題資訊，比對既有項目，取代前建立備份，失敗時回滾。
* 調整內容作者工具：依 Post Type 批次改寫內容作者。
* 查看網站各項設定：顯示外部網路資訊、`wp-config.php` 常數、使用者定義常數、`.htaccess` 與 `.user.ini`。
* 主機 PHP 設定：在 `phpinfo()` 可用時顯示 PHP/主機設定。
* 資料庫檢視與匯出：列出資料庫與資料表，支援單表、全表、背景 SQL 匯出與 `wp-content` 打包。
* 資料庫關鍵字取代：以 Search Replace DB 類別處理序列化資料安全的預覽與實際取代。
* WP 資料庫最佳化：檢視大型 autoload options，清理 orphan/duplicate meta、未使用 option、使用者 metabox，也提供重置 WordPress 的高風險操作。
* 查看最近變更檔案：掃描並分類近期異動的核心、上傳、主題、外掛與其他檔案。
* Hook 執行時間除錯：登入狀態下加上 `?debug` 時，在 admin bar 顯示 hook 執行時間統計。

= Dev Tools: Snippets - Mxp.TW（常用片段與站台行為） =

Snippets 子外掛會直接接管多個 WordPress hook，適合用 `wp-config.php` 先定義 `MDT_*` 常數後再啟用。

* 安全強化：停用 XML-RPC；匿名 REST Users 路由統一回 404；原生作者頁與使用者 sitemap 不提供帳號枚舉；設定過公開顯示名稱的作者會連到同名作者的專用搜尋，login 衍生的預設「小編」維持不可點擊；oEmbed、傳統佈景與區塊佈景共用作者顯示名遮蔽；另移除多種前端 metadata/oEmbed/shortlink 輸出、隱藏頭像並停用 self-ping。
* HTTP 標頭：動態前台回應會停用舊式瀏覽器 XSS Auditor，輸出 MIME sniffing、同源 frame、cross-domain policy 與 referrer policy 防護；HSTS 應由 nginx、Apache、Load Balancer 或 CDN 在所有 HTTPS 回應統一設定。`script-src` 等資源載入 CSP 不由此外掛預設接管。
* 檔案修改保護：預設啟用 `DISALLOW_FILE_MODS` / `DISALLOW_FILE_EDIT`，並保護指定管理員不被一般後台列表、編輯、刪除或降權流程影響。
* 登入與後台調整：登入頁 Logo、登入後導向、管理信箱同步、註冊開關、封鎖使用者登入、顯示內容/分類/使用者 ID、使用者註冊時間欄位、隱藏非管理員更新提示與 Customize 選單。
* 登入頁 Logo：在 WordPress 載入前定義 `MDT_LOGINPAGE_LOGO_URL`；只接受不含帳密的 HTTP/HTTPS URL。中文網域、路徑、查詢與 fragment 會正規化為 Punycode／percent-encoding，既有 `%XX` 編碼不會重複處理。
* 媒體與上傳政策：可停用縮圖產生、停用大圖縮放、上傳圖片大小限制、自動填入圖片標題/alt/content，並對特權管理員與一般使用者套用不同的檔案大小與 MIME 規則。
* Bot/垃圾防護：WordPress 公開登入、註冊、忘記/重設密碼、多站註冊、留言與文章密碼表單，以及 WooCommerce、Contact Form 7 已支援表單，預設使用 action-bound honeypot、短效簽章 token 與前端 PoW；未安裝選用外掛時不會攔截請求。
* 留言預設白名單：新內容預設只讓 `post` 開放留言，`page`、附件、商品與其他自訂 post type 預設關閉；首次由管理員載入後台時，既有非白名單內容也會一次性關閉，但保留既有留言。
* 前台 Basic Auth：可啟用簡易前台驗證，並以指定 query key/cookie 暫時略過。
* 外部 HTTP 請求管控：可封鎖指定網域，或啟用全域封鎖後只允許白名單。
* 站台健康回報與自動更新排程：可透過排程回報站台資訊，也可在排程內更新指定外掛。
* 網域到期檢查：Dashboard widget 顯示 `home_url()`、`site_url()`、多站、額外指定網域與 filter 網域的 RDAP/WHOIS 結果，包含到期日、註冊商、狀態、DNSSEC、Name Server、原始資料與通知狀態。

安全標頭設定：

* `MDT_ENABLE_SECURITY_HEADERS`：預設 `true`。控制 Snippets 對 WordPress 動態前台回應加入的安全標頭與同源 frame 防護；設為 `false` 不會移除 nginx、Apache、Load Balancer 或 CDN 在 WordPress 外層設定的標頭。

登入後跳轉設定：

* `MDT_ENABLE_LOGIN_REDIRECT`：預設 `true`。登入請求帶有 WordPress 驗證通過的明確 `redirect_to` 時優先返回該位置；未指定時，`editor`、`administrator`、`author`、`shop_manager` 會前往後台，其他角色沿用 WordPress 原始目的地。設為 `false` 時完全交回 WordPress 處理。
* `mxp_dev_admin_roles` filter：調整未指定 `redirect_to` 時要導向後台的角色清單。

留言開關政策：

* `MDT_ENABLE_COMMENT_DEFAULT_CLOSED`：預設 `true`。設為 `false` 時不改寫新內容預設值、不執行一次性遷移，也不攔截既有項目的留言狀態；若先前已完成遷移，停用功能不會自動還原已儲存的 `comment_status`。
* `MDT_COMMENT_DEFAULT_OPEN_POST_TYPES`：新內容預設開放留言的 post type，預設為 `array('post')`。可在外掛載入前以 `wp-config.php` 常數替換完整陣列，或使用 `mxp_dev_comment_default_open_post_types` filter 調整。
* 功能啟用後，具 `manage_options` 權限的管理員首次載入該站後台時，會把既有且不在白名單內的 `comment_status=open` 一次性改為 `closed`；既有留言與 `ping_status` 不變。多站環境各站分別執行。
* 白名單只決定新內容的預設值與首次遷移範圍，不是永久封鎖規則。遷移完成後以 WordPress 原生單篇「允許留言」狀態為準：管理員可手動開放任何頁面、附件、商品或 CPT，也可關閉單篇文章。日後增加白名單 post type 不會自動重開舊內容。
* 更新後應清除頁面/CDN 快取，避免已關閉內容的舊快取仍顯示表單；WordPress 接收留言時仍會依資料庫狀態拒絕已關閉項目。

Honeypot 常用設定與行為：

* `MDT_ENABLE_LOGIN_BOT_FUCKOFF`：預設 `true`。保護 WordPress 登入、註冊、忘記密碼、重設密碼、多站註冊及文章密碼表單。
* `MDT_ENABLE_COMMENT_SPAM_FUCKOFF`：預設 `true`。保護 WordPress 標準留言與附件留言。
* `MDT_ENABLE_WOOCOMMERCE_HONEYPOT`：預設 `true`。完整保護 WooCommerce My Account/Classic 登入、註冊、忘記密碼、重設密碼，以及 Classic 商品評論與 `woocommerce/product-review-form` block。標準 form hook／`comment_form()` 會正常注入；主題覆寫模板即使漏掉內部 hook，只要仍由 WooCommerce `wc_get_template()` 載入並保留原生提交欄位，也會由 template fallback 精準補入一次。未安裝 WooCommerce 時不會攔截一般請求；可在外掛載入前定義為 `false` 關閉整合。
* `MDT_ENABLE_CONTACT_FORM_7_HONEYPOT`：預設 `true`。保護 Contact Form 7 表單，challenge 綁定個別表單 ID，驗證失敗由 Contact Form 7 原生 spam 流程處理。未安裝 Contact Form 7 時不會攔截一般請求；可在外掛載入前定義為 `false` 關閉整合。
* `MDT_HONEYPOT_MIN_SECONDS`：challenge 簽發後最短可提交秒數，預設 `2`。
* `MDT_HONEYPOT_POW_DIFFICULTY`：所有受保護表單的 SHA-256 Hashcash 前導零位元難度，預設 `18`，有效範圍 `8`～`24`；每增加一位，平均求解量約加倍。實際時間依裝置與瀏覽器而異，無法保證固定秒數。
* `MDT_HONEYPOT_POW_MAX_SECONDS`：所有受保護表單的 PoW challenge 最長有效秒數，預設 `60`，有效範圍 `3`～`300`。
* 所有已支援表單都要求 payload-bound PoW。challenge 僅簽署 action、context、時間、難度與隨機值；密碼和表單內容不會為取得 challenge 而額外傳到 token endpoint。Worker 在本機將 challenge、最終 scalar 表單 payload hash 與 counter 一起求解，伺服器由最終 POST 重建 payload hash 後無狀態驗證。
* 前端會在輸入停止後背景準備 proof；即使瀏覽器或密碼管理器直接自動填入帳密而未觸發 input event，送出攔截器仍會重新讀取當下 `FormData`、等待 proof 完成，再恢復原生 submit event。計算期間提交按鈕會暫停並以 `aria-busy`／live status 表示；Worker、Web Crypto 或 challenge endpoint 失敗時保留表單內容並顯示錯誤，不會送出一個必定被後端拒絕的請求。
* payload canonicalization 支援 scalar、重複欄位與巢狀陣列，統一換行並排除 token、proof、動態誘餌及由 reCAPTCHA／hCaptcha／Turnstile 自行驗證且可能在 submit listener 後才產生的短效 response。檔案 input 的二進位內容不納入 payload hash，但同一份表單的其他欄位仍須完成 PoW。
* challenge endpoint 使用 `no-store` POST，且 token 無伺服器 session、資料表或 transient；頁面/CDN 快取、表單 reset 與 BFCache 還原都不會放寬後端驗證。完全相同 payload/proof 在有效期內仍可重送，登入節流、留言去重與其他業務限制仍由 WordPress／整合外掛處理。
* 版本更新後須清除既有頁面/CDN 快取，並確認 `admin-ajax.php?action=mxp_honeypot_token` 不被快取；舊版 `v2`／`v3` token 與未載入新版 Worker 的表單會 fail closed。
* 主題直接 `include` 自製表單、移除 WooCommerce 原生 nonce/提交欄位、改走自訂 AJAX/REST endpoint，已脫離 WooCommerce template/hook 契約，無法安全推斷表單語意，必須另外使用對應的輸出與 server-side 驗證 hook 整合。WPForms，以及 WooCommerce Checkout Blocks/Store API 結帳建帳與 Order Confirmation 延後建帳，目前也不在保護範圍內。

網域到期檢查常用設定：

* `MDT_DOMAIN_EXPIRY_CHECK`：是否啟用網域到期檢查，預設 `true`。
* `MDT_DOMAIN_EXPIRY_NOTICE_DAYS`：到期通知門檻，預設 `90, 60, 30, 14, 7, 3, 1` 天。
* `MDT_DOMAIN_EXPIRY_EXTRA_DOMAINS`：額外指定檢查網域，支援陣列或逗號分隔字串。
* `MDT_DOMAIN_EXPIRY_OBSERVE_HOSTS`：是否自動記錄非設定來源的 HTTP_HOST，預設 `false`。
* `MDT_DOMAIN_EXPIRY_OBSERVED_HOST_RETENTION_DAYS`：觀察到的 HTTP_HOST 紀錄保留天數，預設 `180`。
* `MDT_DOMAIN_EXPIRY_MAX_DOMAINS_PER_RUN`：單次排程最多查詢數量，預設 `20`。
* `MDT_DOMAIN_EXPIRY_STORE_RAW_DATA`：是否儲存 RDAP/WHOIS 原始資料，預設 `true`。

= Dev Tools: Site Manager - Mxp.TW（多站管理） =

Site Manager 用來把多個 WordPress 站台整理成一個維運主控台，同時保留既有匯出/匯入與快速登入流程。

* 匯出目前站台資訊：包含站台 URL、站名、管理員信箱、IPv4、IPv6、DNS A/NS 記錄、Whois/網域到期資訊、Site Manager 版本、登入協議版本、外掛/佈景主題/核心更新、PHP/MySQL 版本、檔案異動、cron 狀態與環境快照。
* 匯入其他站台匯出的設定字串，經格式、URL、passkey 與欄位結構驗證後仍儲存在 `mxp_dev_sites_info_db` 站台選項；新版主控台會同步寫入 `mxp_sm_sites`、`mxp_sm_site_credentials`、`mxp_sm_site_snapshots`、`mxp_sm_site_events`、`mxp_sm_site_jobs`、`mxp_sm_site_job_logs` 等資料表。
* 主控台顯示總覽卡片、站台狀態、環境/客戶/標籤備註、更新數、網域到期、最近 heartbeat、事件紀錄與遠端工作紀錄；後台輸出會移除 passkey/secret/token/HMAC/signature 並轉義顯示內容。
* 快速登入：新版站台使用具版本標記的加密 token、HMAC-SHA256、audience、jti 與 15 秒時間窗；目標站會以 transient 防止同一 token 重放。舊版匯入資料仍維持相容的 legacy token，建議重新匯入以升級登入協議。
* 安全配對：先以既有匯出字串內的 passkey 作一次性 bootstrap，完成後改用獨立 remote secret；Hub/Agent REST 請求使用 HMAC-SHA256 簽署 canonical request、5 分鐘時間窗與 replay 防護。
* 遠端控制開放 Level 0/1 安全動作：heartbeat、capabilities、inventory、refresh_snapshot、clear_object_cache、flush_rewrite_rules、trigger_cron、rotate_pair_credential、issue_login_ticket。一次性登入票券只在當次 AJAX 回應交付，不寫入 job 結果或 dashboard state。
* Level 2 中風險操作已提供基本中控能力：update_plugin、update_theme、update_core_minor、activate_plugin、deactivate_plugin。每站預設關閉，需在該站 policy 啟用；production 站另需勾選 production Level 2。所有 Level 2 都必須先 dry-run，由後端簽發 10 分鐘 confirmation token，execute 時再驗 token；同站同時只允許一個 Level 2 running job，multisite execute 預設拒絕。
* Level 3（DB search replace/reset、刪除或任意安裝外掛/佈景、編輯檔案、使用者/角色變更等）仍預設未實作且政策拒絕，不顯示可執行按鈕。
* 重置站台密鑰：刪除本機 passkey 並在下次使用時重建；既有匯出字串會因此失效，已配對的 remote secret 也應解除配對後重新建立。
* 支援單站 Tools 頁面與 multisite Network Admin 頁面；頁面與 AJAX 使用同一個可 filter 的 capability。

匯出的字串包含 passkey，等同可請求快速登入與配對 bootstrap 的高權限憑證。請只在可信任管理員與可信任傳輸渠道中保存或分享；若曾外洩，請立即重置站台密鑰、解除配對並重新匯出/配對。

= Dev Tools: Hide Login Page - Mxp.TW（登入路徑防護） =

Hide Login Page 沒有設定頁，透過常數控制：

* `MDT_LOGIN_PATH`：預設 `admin-staff`，登入網址會變成 `/admin-staff/`；未啟用 pretty permalink 時使用 `/?admin-staff`。預設字串與外掛原始碼都是公開資訊，正式站必須在 WordPress 載入前定義每站不同且不可預測的值。
* `MDT_LOGIN_PATH_DISPLAY`：預設 `true`；設為 `false` 時可在外掛列表隱藏此子外掛。

啟用後，`wp-login.php`、`/login`、`wp-register`、`wp-activate` 與非 multisite 的 `wp-signup` 會走 404 流程；未登入的 `/wp-admin/` 請求也會被導到 `/404`。此外掛也會改寫 WordPress 產生的登入 URL、redirect URL、welcome email 中的登入連結，以及 WooCommerce 密碼重設連結。公開文章密碼表單會改用只接受 `POST action=postpass` 的原生處理入口，不再輸出自訂登入路徑。
登入路徑隱藏只能降低通用掃描雜訊，不是身分驗證或存取控制。若主題、區塊、小工具或第三方外掛刻意向匿名訪客輸出 `wp_login_url()`／註冊連結，自訂路徑仍會出現在公開 HTML；此需求與「路徑不可公開」互斥，應移除該公開登入元件，並另外啟用強密碼、MFA、速率限制與此外掛的登入 honeypot。

= Dev Tools: Feedback Reporter - Mxp.TW（全站問題回報） =

Feedback Reporter 沒有設定頁，透過 `MDT_FEEDBACK_REPORTER_*` 常數控制。啟用外掛後預設啟用回報功能；只允許登入並符合 role / user ID 規則的使用者在前台與後台看到回報入口。若要關閉，可在 `wp-config.php` 將 `MDT_FEEDBACK_REPORTER_ENABLE` 定義為 `false`。

* 前台使用明確的「回報問題」浮動按鈕；後台使用低干擾的小型「回報」入口，避免遮住主要操作或一直提醒使用者回報。
* 使用者點擊後才啟動回報流程，可選擇擷取目前頁面「當下捲動視野」，或開啟獨立錄影控制器錄製最長 60 秒短片；控制器留在獨立視窗中，原頁跳轉或重新整理不會中斷錄影，錄影中會顯示倒數與停止按鈕，不必錄滿一分鐘。
* 截圖模式可在截圖上畫框、箭頭、文字、自由畫筆與馬賽克；錄影模式會送出錄影檔與自動產生的封面截圖。若自動 DOM 截圖無法呈現互動畫面，可上傳 PNG/JPEG/WebP 或從剪貼簿貼上外部截圖取代，再填寫問題描述。
* 前端只送到本站 REST endpoint；webhook URL 與 secret 不會輸出到瀏覽器。
* WordPress server-side 驗證登入、nonce、role/user ID、rate limit、截圖與錄影 MIME，並在 webhook 前重新檢查與壓縮截圖大小；未設定 webhook 時仍會保存本機 log/截圖/錄影，設定 webhook 後才送出外部通知；匿名回報也會保存解析後的回報 IP 與 IP hash，方便追蹤濫用來源。
* 回報 IP 會優先使用可信任反向代理還原出的真實用戶 IP：預設會從 Cloudflare 官方 `ips-v4` / `ips-v6` 清單取得並快取可信 edge CIDR，抓取失敗時才回退到內建 Cloudflare 範圍；只有當 `REMOTE_ADDR` 落在可信代理 CIDR 內才讀取 `CF-Connecting-IP`、`CF-Connecting-IPv6`、`True-Client-IP`、`X-Real-IP`、`Forwarded` 或 `X-Forwarded-For`，避免直接打到 origin 的請求偽造 client IP header。若 origin 已由防火牆限制只能經 Cloudflare 進站，也仍建議保留此閘門作為防呆；不建議無條件信任 header。
* log 目錄預設在 `wp-content/uploads/mxp-dev-tools/feedback-reporter/`，每次回報會寫入不可預測的隨機子目錄與隨機檔名；Apache/LiteSpeed 會透過 `.htaccess` 關閉目錄列表並拒絕 JSON log 直連，但允許圖片/影片媒體檔讓內部 webhook 連結可直接開啟，nginx 需由站台自行決定是否加上等效規則；再依保留天數與檔案數上限自動清理，移除 Feedback Reporter 子外掛時預設會刪除 log/截圖/錄影。
* Discord webhook 會以附件方式上傳截圖並在訊息中預覽；Slack incoming webhook 只送出 JSON + Block Kit 文字欄位與 Log / 檔案連結，不使用 image block，避免站台圖片 URL 被主機資安策略阻擋時造成整包通知失敗。

常用常數：

* `MDT_FEEDBACK_REPORTER_ENABLE`：是否啟用全站回報，預設 `true`；可設為 `false` 關閉。
* `MDT_FEEDBACK_REPORTER_ADMIN_ENABLE`：是否在 `wp-admin` 輸出低干擾後台回報入口，預設 `true`。
* `MDT_FEEDBACK_REPORTER_ADMIN_BUTTON_MODE`：後台入口樣式，預設 `subtle-tab`，另可用 `compact-pill`。
* `MDT_FEEDBACK_REPORTER_WEBHOOK_URL`：接收回報的 webhook URL；預設要求 HTTPS，未設定時仍可回報並保存本機 log/截圖/錄影，但不送出外部通知。
* `MDT_FEEDBACK_REPORTER_WEBHOOK_FORMAT`：webhook payload 格式，預設 `auto`；Discord 與 Slack incoming webhook URL 會自動送出相容格式，也可設為 `generic`、`discord` 或 `slack`。
* `MDT_FEEDBACK_REPORTER_WEBHOOK_SECRET`：webhook HMAC 簽章 secret，預設空字串。
* `MDT_FEEDBACK_REPORTER_WEBHOOK_REQUIRE_HTTPS`：是否要求 webhook URL 使用 HTTPS，預設 `true`；設為 `false` 時可接受 HTTP，但仍會拒絕 private/reserved IP。
* `MDT_FEEDBACK_REPORTER_WEBHOOK_SSL_VERIFY`：是否驗證 HTTPS 憑證，預設 `true`；設為 `false` 時可接受自簽憑證。
* `MDT_FEEDBACK_REPORTER_ALLOWED_ROLES`：允許回報的角色，預設 `administrator`。
* `MDT_FEEDBACK_REPORTER_ALLOWED_USER_IDS`：額外允許回報的使用者 ID。
* `MDT_FEEDBACK_REPORTER_DENIED_USER_IDS`：禁止回報的使用者 ID，優先權最高。
* `MDT_FEEDBACK_REPORTER_DENIED_PATHS`：不輸出回報入口的 path prefix，預設只排除 `/wp-login.php`。
* `MDT_FEEDBACK_REPORTER_LOG_RETENTION_DAYS`：本機 log/截圖/錄影保留天數，預設 `30`。
* `MDT_FEEDBACK_REPORTER_MAX_LOG_FILES`：本機 log/截圖/錄影檔案數上限，預設 `500`。
* `MDT_FEEDBACK_REPORTER_TRUST_PROXY_HEADERS`：是否在可信反向代理後方解析真實用戶 IP，預設 `true`。
* `MDT_FEEDBACK_REPORTER_TRUSTED_PROXY_CIDRS`：Cloudflare 官方清單抓取失敗時使用的 fallback Cloudflare 代理 CIDR；此閘門是為了防止繞過 CDN 直打 origin 時偽造 `CF-Connecting-IP` / `X-Forwarded-For`。
* `MDT_FEEDBACK_REPORTER_ADDITIONAL_TRUSTED_PROXY_CIDRS`：額外信任的自家 proxy / load balancer CIDR，會與 Cloudflare 官方清單合併；為相容舊設定，若 `MDT_FEEDBACK_REPORTER_TRUSTED_PROXY_CIDRS` 內含不屬於內建 Cloudflare fallback 的 CIDR，也會視為額外可信代理。
* `MDT_FEEDBACK_REPORTER_CLOUDFLARE_IPS_AUTO_UPDATE`：是否自動抓取 Cloudflare 官方 IP 清單更新可信代理 CIDR，預設 `true`。
* `MDT_FEEDBACK_REPORTER_CLOUDFLARE_IPS_CACHE_TTL`：Cloudflare IP 清單快取秒數，預設 7 天；抓取失敗時使用上一份有效 transient 或 `MDT_FEEDBACK_REPORTER_TRUSTED_PROXY_CIDRS` fallback。
* `MDT_FEEDBACK_REPORTER_CLOUDFLARE_IPS_V4_URL` / `MDT_FEEDBACK_REPORTER_CLOUDFLARE_IPS_V6_URL`：Cloudflare IP 文字清單來源，預設 `https://www.cloudflare.com/ips-v4` 與 `https://www.cloudflare.com/ips-v6`。
* `MDT_FEEDBACK_REPORTER_MAX_VIDEO_SECONDS`：錄影模式最長秒數，預設 `60`。
* `MDT_FEEDBACK_REPORTER_MAX_VIDEO_BYTES`：錄影檔案大小上限，預設 `50 MiB`。
* `MDT_FEEDBACK_REPORTER_DELETE_LOGS_ON_UNINSTALL`：移除 Feedback Reporter 子外掛時是否刪除 log/截圖/錄影，預設 `true`。

= 使用風險 =

* 此套件設計給可信任管理員、開發者與站台維護者使用，不適合開放給一般後台使用者。
* 搜尋取代、資料庫最佳化、WordPress 重置、批次改作者、外掛/主題取代都會改寫資料或檔案；操作前請先確認備份可還原。
* 主要工具箱會讀取並顯示 `wp-config.php`、`.htaccess`、`.user.ini`、PHP 設定與資料庫資訊。
* `ZipArchive`、網路連線、檔案系統權限與主機 PHP 限制會影響打包、匯出、安裝、替換與前端回報轉送功能。

== Installation ==

1. Upload the plugin files to the `/wp-content/plugins/mxp-dev-tools/` directory, or install the plugin from the WordPress Plugins screen.
2. Activate the main `Dev Tools - Mxp.TW` plugin through the **Plugins** screen in WordPress.
3. Activate optional sub-plugins only when needed: `Dev Tools: Snippets - Mxp.TW`, `Dev Tools: Site Manager - Mxp.TW`, `Dev Tools: Hide Login Page - Mxp.TW`, or `Dev Tools: Feedback Reporter - Mxp.TW`.
4. Open 「開發工具箱」 or the relevant sub-plugin admin page in the WordPress admin menu.
5. For advanced behavior, define the documented `MDT_*` constants in `wp-config.php` before WordPress loads.

== Frequently Asked Questions ==

= Why are there multiple plugin entries after installation? =

The package intentionally contains a main plugin plus optional sub-plugins. This lets a site enable only the tools it needs while keeping one shared release package and update path.

= Should I activate every sub-plugin? =

No. Activate the main toolbox for development and maintenance tools. Activate Snippets, Site Manager, or Hide Login Page only when the site needs those behaviors, because each sub-plugin changes runtime hooks.

= Where are Snippets settings configured? =

Most Snippets behavior is controlled with `MDT_*` constants defined before WordPress loads, usually in `wp-config.php`. Some behavior also has filters documented in the source.

= How do I change the WordPress login Logo? =

Define `MDT_LOGINPAGE_LOGO_URL` before WordPress loads, for example `define('MDT_LOGINPAGE_LOGO_URL', 'https://example.com/uploads/品牌標誌.png');`. Snippets accepts Unicode in the host, path, query, and fragment, then normalizes the URL before emitting login-page CSS. Only HTTP/HTTPS URLs without embedded credentials are accepted. WordPress media attachments use their stored dimensions; external images use the safe default Logo size and are fetched by the browser rather than by the WordPress server.

= Will observed HTTP_HOST domains be shown on the domain expiry dashboard? =

No by default. Since 3.5.9, `MDT_DOMAIN_EXPIRY_OBSERVE_HOSTS` defaults to `false`, and observed-only hosts are kept behind a separate detail page instead of the main dashboard list.

= How do I add extra domains to the expiry check? =

Define `MDT_DOMAIN_EXPIRY_EXTRA_DOMAINS` in `wp-config.php` as an array or comma-separated string.

= How do I change the hidden login URL? =

Define `MDT_LOGIN_PATH` before WordPress loads. The default slug is `admin-staff`.

= Is Site Manager safe to share or pair across sites? =

No. The exported site string includes the passkey used for quick-login tokens and the first pairing bootstrap. Treat it like an administrator credential, share it only through trusted channels, and rotate the passkey plus re-pair the site if it may have leaked. After pairing, remote control uses a separate encrypted shared secret, HMAC-signed requests, replay protection, and only Level 0/1 low-risk actions.

= How do I configure Feedback Reporter? =

Activate the Feedback Reporter sub-plugin. The reporter is enabled by default after activation and can save local logs/screenshots/recordings even before a webhook is configured; define `MDT_FEEDBACK_REPORTER_ENABLE` as `false` to disable it. Set `MDT_FEEDBACK_REPORTER_WEBHOOK_URL` before WordPress loads when you want external notifications. `auto` detects Discord and Slack incoming webhook URLs; set `MDT_FEEDBACK_REPORTER_WEBHOOK_FORMAT` to `generic`, `discord`, or `slack` only when you need to force a payload type. By default the webhook must be HTTPS with a valid certificate; set `MDT_FEEDBACK_REPORTER_WEBHOOK_REQUIRE_HTTPS` or `MDT_FEEDBACK_REPORTER_WEBHOOK_SSL_VERIFY` to `false` only for trusted internal/self-signed receivers. Use `MDT_FEEDBACK_REPORTER_ALLOWED_ROLES`, `MDT_FEEDBACK_REPORTER_ALLOWED_USER_IDS`, and `MDT_FEEDBACK_REPORTER_DENIED_USER_IDS` to limit who can submit reports.

= Does Feedback Reporter expose my webhook secret to visitors? =

No. The browser only receives the local REST endpoint and nonce. WordPress sends the webhook server-side and signs it with `MDT_FEEDBACK_REPORTER_WEBHOOK_SECRET` when configured.

= Do I need to back up before using database or replacement tools? =

Yes. Database search/replace, optimization, cleanup, reset, bulk author changes, and file replacement tools can modify production data or files. Always keep a verified backup before running destructive actions.

== Screenshots ==

1. ** 常用外掛操作列表 ** - 作者常用外掛安裝、啟用批次操作區域。

2. ** Themeforest 外掛、主題下載 ** -  輸入 Themeforest 建立的授權碼取得帳號下購買的主題或外掛，線上安裝。

3. ** 批次修改全站內容作者 ** - 指定內容類型全站調整作者權限，讓客戶帳號方便作業。

4. ** 超快速搜尋外掛工具 ** - 作者自行整理的官方外掛庫，每日更新，用來快速找對外掛資源。

5. ** 主題打包工具 ** - 網站主題一鍵打包下載功能。

6. ** 外掛列表頁面打包工具 ** - 網站外掛一鍵打包下載功能。

7. ** 資料庫與資料表檢視與匯出工具 ** - 查看資料庫與資料表設定，並提供匯出備份功能。

8. ** 資料庫關鍵字搜尋與取代工具 ** - 指定或全站資料表掃描固定字眼並取代的功能，搬家時換網域常用。

== Upgrade Notice ==
= 3.6.20 =
Snippets 新增預設關閉留言的 post type 白名單政策：文章預設開放，頁面、附件、商品與其他 CPT 預設關閉；既有內容會執行一次性遷移，之後仍可用 WordPress 原生單篇控制明確開放或關閉。

= 3.6.19 =
Snippets 補齊 Contact Form 7 5.2.x 的舊版 spam filter 契約；已在 WordPress 5.5、PHP 7.4、WooCommerce 4.5.0 與 Contact Form 7 5.2.1 的最低版本測試站完成 Core、WooCommerce、CF7 與忘記密碼瀏覽器回歸。

= 3.6.18 =
Snippets 的 WooCommerce 與 Contact Form 7 PoW 整合改為預設開啟；WordPress Core 與 WooCommerce 忘記／重設密碼表單均納入預設 payload-bound PoW，未安裝選用外掛時保持無作用，既有常數仍可明確關閉個別整合。

= 3.6.17 =
Snippets 的所有已支援表單統一要求無狀態、短效且綁定最終 scalar payload 的 SHA-256 Proof-of-Work；前端會攔截直接送出並等待計算完成，瀏覽器自動填入帳密後立即登入不會被誤判為缺少 proof。

= 3.6.16 =
Snippets 的 WordPress Core 與選用 WooCommerce 留言防護新增無狀態、短效且綁定最終表單內容的 SHA-256 Proof-of-Work；瀏覽器以本機 Worker 背景求解，伺服器低成本驗證，頁面/CDN 快取不會共用 challenge。


= 3.6.15 =
Snippets 在不恢復原生作者頁與帳號識別資訊的前提下，讓明確設定的公開顯示名稱連到專用搜尋，列出所有同名作者的公開文章；一般全文搜尋與預設「小編」行為維持不變。

= 3.6.14 =
Snippets 補齊 oEmbed、REST Users、作者彙整頁、使用者 sitemap 與區塊作者名稱的帳號枚舉防護；Hide Login Page 的公開文章密碼表單不再輸出自訂登入路徑。

= 3.6.13 =
Snippets 強化登入頁 Logo URL 正規化與輸出安全，整理動態前台安全 HTTP 標頭，並修正登入後目的地優先序與移除不安全的舊 cookie 跳轉流程。

= 3.6.12 =
Snippets honeypot 完整保護 WordPress 公開內建表單，新增具抗快取 token 的 Contact Form 7 與 WooCommerce 獨立選用整合；表單 adapter 已透過註冊契約、registry 與共用留言路由解耦，並完成 WordPress 5.5／PHP 7.4 相容驗證。

= 3.6.11 =
Site Manager 強化遠端新增外掛流程：支援 WordPress.org slug 與外部 ZIP URL（如 GitHub release、私有套件下載）預檢、確認後安裝；同版改善配對、批次變更、操作結果、快照摘要與 DB 版本顯示。

= 3.6.10 =
Feedback Reporter 修正 Painterro 內含 Lodash 覆蓋 WordPress Underscore 的問題，避免後台媒體庫與特色圖片選取流程出現 `_.contains is not a function`。

= 3.6.9 =
Feedback Reporter 強化真實用戶 IP 紀錄：可信 Cloudflare 代理範圍會自官方清單快取更新，匿名回報也會保存解析後 IP；同版修正回報介面樣式隔離與 Feedback Logs 長字串欄位溢出。

= 3.6.8 =
Feedback Reporter 調整 Slack incoming webhook 通知：截圖改以文字連結與後台 Log 入口呈現，不再送出 Slack image block，避免站台圖片 URL 被主機資安策略阻擋時造成整包 webhook 回報失敗。

= 3.6.7 =
Feedback Reporter 新增可選的匿名前台回報第二路徑（預設關閉），開啟後未登入訪客可沿用同一套截圖/錄影流程送出回報；同版修正前台與後台在捲動位置點「回報」時被瀏覽器重設到頁面頂端的問題。

= 3.6.6 =
Feedback Reporter 在支援的桌機瀏覽器會優先使用 Browser Screen Capture API 的螢幕/視窗/分頁分享選擇器擷取目前畫面，並新增最長預設 60 秒的獨立視窗錄影控制器；原頁跳轉不會中斷錄影，錄影中會顯示倒數與停止按鈕，可提前結束；同時保留較高解析度的標註輸出，不再因預覽縮放降低實際截圖像素。

= 3.6.5 =
Feedback Reporter Logs 後台頁面現在會直接顯示截圖縮圖與詳細預覽，不再只列出本機檔案路徑；同版修正 WordPress Playground Test Preview 藍圖安裝順序。

= 3.6.4 =
修正 Feedback Reporter 捲動後的 viewport 截圖，避免 fixed/sticky 底部操作列在桌機與手機截圖中位置錯亂；同時移除不穩定的「貼上截圖」按鈕，保留 Ctrl/⌘+V 貼上與檔案上傳。

= 3.6.3 =
修正 Feedback Reporter 截圖對應目前捲動視野，並新增上傳或貼上圖片取代自動截圖，避免互動畫面無法由 DOM 截圖呈現時無法回報。

= 3.6.2 =
Feedback Reporter 啟用後預設可保存本機回報；log 頁面會提示 webhook 設定狀態，並新增 Slack incoming webhook 與 WordPress Playground 即時預覽支援。

= 3.6.1 =
更新 Feedback Reporter 使用的 SnapDOM 至 3.2.0，並確認截圖、遮罩、SEO 資訊、後台 log 檢視、webhook 補送與 RWD 介面相容。

= 3.6.0 =
新增 Feedback Reporter 子外掛：登入用戶可在前台與後台擷取並標註目前頁面，填寫問題描述後由 WordPress server-side 安全轉送指定 webhook，並以檔案型 log/截圖做薄紀錄與自動清理。


== Changelog ==
= 3.6.20 =

* 新增預設啟用的 `MDT_ENABLE_COMMENT_DEFAULT_CLOSED` 留言政策；新內容只有 `post` 預設開放留言，`page`、附件、WooCommerce 商品與其他非白名單 post type 預設關閉。
* `MDT_COMMENT_DEFAULT_OPEN_POST_TYPES` 常數與 `mxp_dev_comment_default_open_post_types` filter 可調整新內容白名單；功能可完整停用，不與 honeypot／PoW adapter 耦合。
* 管理員首次載入各站後台時，分批關閉既有非白名單內容並清除 post cache；既有留言與 `ping_status` 保留。遷移完成前，非白名單內容在執行期維持 fail closed。
* 遷移後以 WordPress 原生單篇留言狀態為最終依據；已透過實際 Gutenberg Discussion 控制開啟、儲存、關閉並驗證資料庫狀態，也確認明確開放的頁面可通過既有 payload-bound PoW 留言流程。
* DDEV 現行環境 WordPress 7.1.3、PHP 8.2.30、WooCommerce 11.2.1、Contact Form 7 6.1.7，以及最低環境 WordPress 5.5、PHP 7.4.33、WooCommerce 4.5.0、Contact Form 7 5.2.1，均完成政策、Core、WooCommerce 與 CF7 回歸。

= 3.6.19 =

* Contact Form 7 adapter 相容 5.2.x 僅傳入 spam flag 的 `wpcf7_spam` 舊契約，會安全取得該次 `WPCF7_Submission` 後執行相同 payload-bound PoW 驗證，不再把具有效 proof 的舊版 CF7 提交誤標為 spam。
* DDEV 最低相容性矩陣實測 WordPress 5.5、PHP 7.4.33、WooCommerce 4.5.0 與 Contact Form 7 5.2.1；Core、Classic WooCommerce、CF7 回歸及 Core／WooCommerce 忘記密碼瀏覽器直接送出均通過。
* 回歸腳本在舊版 CF7 的 WP-CLI 建表單流程明確指定站台 URL，並在替換 WooCommerce My Account 測試頁後刷新 rewrite rules，排除 CLI 缺少主機資訊與舊 rewrite 快取造成的假失敗。

= 3.6.18 =

* `MDT_ENABLE_WOOCOMMERCE_HONEYPOT` 與 `MDT_ENABLE_CONTACT_FORM_7_HONEYPOT` 預設值改為 `true`，安裝 Snippets 後即保護目前已支援的 Core、WooCommerce 與 Contact Form 7 公開表單。
* WordPress Core `lostpassword`／`retrievepassword` 與 WooCommerce `lost-password` render、challenge、submit validation 路徑納入預設回歸與瀏覽器驗證。
* WooCommerce 或 Contact Form 7 未安裝時，預設開關只註冊安全的 adapter hooks，不會宣告不存在的 token context 或攔截一般請求；需要停用時仍可在外掛載入前將個別常數設為 `false`。

= 3.6.17 =

* WordPress 登入、註冊、忘記／重設密碼、多站註冊、文章密碼、自訂 shortcode、留言／附件留言，以及啟用後的 WooCommerce 帳號表單、商品評論和 Contact Form 7 全部改用 `v4` payload-bound PoW challenge。
* challenge 不接收密碼或表單內容；本機 Worker 將簽署 token、最終 scalar payload hash 與 counter 一起求解，伺服器由最終 POST 重建 canonical payload 並驗證，維持無狀態與頁面快取相容。
* 前端 submit gate 會處理密碼管理器／瀏覽器自動填入後的立即點擊、Enter 送出、背景 proof 過期、欄位變更、重複點擊、BFCache 與 reset；proof 完成前不送出，失敗時保留輸入並顯示可重試錯誤。
* Contact Form 7 改由原始最終 POST 驗證重複／陣列欄位；檔案 input 的二進位內容不納入 payload hash。移除已無非 PoW 路徑使用的 `MDT_HONEYPOT_MAX_SECONDS`。

= 3.6.16 =

* WordPress Core 留言與啟用後的 WooCommerce 商品評論 token 現在綁定文章/附件 ID、父留言、作者、Email、網址與留言內容；任一欄位變更都會使既有 proof 失效。
* 新增本機 SHA-256 Web Worker，在留言欄位停止輸入後背景準備、送出時等待必要 proof；challenge 由既有 `no-store` POST endpoint 短效核發，不載入 CDN 或第三方服務。
* 伺服器以 HMAC、payload hash 與單次 SHA-256 無狀態驗證，不新增資料表、session、transient 或外部 API；完全相同 payload 的重送仍交由 WordPress Core 重複留言檢查。
* 新增 `MDT_HONEYPOT_POW_DIFFICULTY`（預設 18）與 `MDT_HONEYPOT_POW_MAX_SECONDS`（預設 60）供站台依裝置實測調整難度與期限。


= 3.6.15 =

* Snippets 將明確設定的公開顯示名稱連到專用作者搜尋；搜尋以完整顯示名稱比對使用者，支援多位同名作者，並沿用 WordPress 公開文章、密碼保護與分頁限制。
* 專用作者搜尋不恢復原生作者 archive、`user_nicename` 或數字 ID；login 衍生的預設「小編」仍不可點擊，普通內容搜尋也不會被擴張為作者搜尋。
* oEmbed 的 `author_url` 與前台作者連結使用相同公開身分規則：明確公開顯示名稱連到專用搜尋，否則維持站台首頁。

= 3.6.14 =

* Snippets 的作者隱藏現在涵蓋 oEmbed `author_name`／`author_url`、區塊佈景直接讀取的 `display_name`、註冊用戶留言的前台與 REST 作者名稱、作者彙整頁，以及 WordPress 5.5 起的使用者 sitemap。
* 匿名 `wp/v2/users` collection、單筆、搜尋與 HEAD 請求統一回相同 404；不再以空陣列保留命中筆數、`X-WP-Total` 或既有 ID／不存在 ID 的狀態差異，已驗證登入的 REST 用戶維持原功能。
* Hide Login Page 的文章密碼表單改用只接受 POST 的原生 `wp-login.php?action=postpass` 處理器，頁面與 RSS 不再洩露 `MDT_LOGIN_PATH`；既有登入路徑與舊入口 404 行為維持不變。
* 文件明確標示預設 `admin-staff` 是公開資訊，登入路徑隱藏只用於降低掃描雜訊；正式站應設定每站唯一值，且不得同時向匿名頁面輸出公開登入元件並期待路徑保密。

= 3.6.13 =

* 登入頁 `MDT_LOGINPAGE_LOGO_URL` 支援中文網域、路徑、query 與 fragment，自動產生 Punycode／percent-encoding 且保留既有 `%XX`；限制 http/https、拒絕內嵌帳密、以帶引號的 CSS URL 輸出，並移除登入請求中的 server-side 外部圖片探測。
* Snippets 安全 HTTP 標頭移除過時的 `X-Content-Security-Policy` 與應由伺服器統一管理的 HSTS，停用舊式 XSS Auditor，並新增 `Referrer-Policy: strict-origin-when-cross-origin`；既有同源 frame 與 MIME sniffing 防護維持不變。
* Snippets 登入後跳轉改為只使用 WordPress `login_redirect` filter：安全的明確目的地優先於角色預設，未指定時才將可管理角色導向後台；移除失效且可由偽造 cookie 觸發外部導向的舊前台 cookie 流程。

= 3.6.12 =

* Snippets honeypot 驗證會拒絕陣列等非字串 token 與留言文章 ID，避免畸形 POST 在 PHP 8 觸發 `explode()` TypeError 與 HTTP 500。
* Snippets honeypot 重構為可註冊 action/context 的核心與表單 adapter：受保護的 WordPress 公開內建表單現在強制要求有效短效簽章 token 與空白動態誘餌欄位，補齊忘記/重設密碼、多站註冊及文章密碼流程；快取頁面會從 `no-store` 端點刷新 token，並保留 WooCommerce Classic 帳號表單保護。
* Honeypot integrations 改由統一 contract 與 registry 註冊；共用留言 router 依優先序隔離 WordPress 留言與 WooCommerce 商品評論，即使個別 integration 關閉也不會被通用規則誤接管，後續新增表單 adapter 不必修改既有 adapter。
* Snippets 新增預設關閉的 Contact Form 7 honeypot adapter；啟用後會注入表單 ID context-bound token，從 capture phase 協調 AJAX submit，並透過 `wpcf7_spam` 在 server-side 阻擋缺少或無效證明的提交。
* Snippets WooCommerce honeypot adapter 改為涵蓋公開 My Account 帳號驗證流程；Customer Account block 導向的帳號表單沿用相同保護，Classic 商品評論與 Product Review Form block 則共用 WordPress `comment_form()` 防護，避免重複注入與驗證。Checkout/Store API/Order Confirmation 建帳仍明確排除。
* Snippets WooCommerce adapter 新增 template-level fallback：主題覆寫 My Account/Classic review 模板即使漏掉表單內 hook，仍會依 WooCommerce nonce 與原生欄位辨識後精準注入，既有標準 hook 輸出則不重複注入。
* Snippets 新增預設關閉的 `MDT_ENABLE_WOOCOMMERCE_HONEYPOT` 獨立開關；未啟用時 WordPress 登入／留言 honeypot 不再連帶注入或驗證 WooCommerce 帳號與商品評論，啟用後則完整開啟 WooCommerce adapter。
* 全套外掛最低需求調整並實測為 WordPress 5.5、PHP 7.4；同步相容舊版 `the_password_form` filter 參數與 AJAX `wp_die()` 會覆寫 Cache-Control 的差異，確保 token endpoint 在 WordPress 5.5 仍回傳 `no-store`。

= 3.6.11 =

* Site Manager 遠端 Level 2 execute 會在已驗證簽章與 policy 後切入管理員 capability context，避免 REST Agent 無登入使用者時 WordPress upgrader 直接拒絕外掛/佈景/核心更新。
* Site Manager 新增外掛操作改為多來源流程：可選 WordPress.org slug 或外部 ZIP URL，ZIP 來源會驗證 `http/https`、`.zip` 路徑與下載主機，執行前會先檢查 ZIP 只含單一有效外掛入口，預檢畫面會顯示來源類型、下載主機、預期 slug、既有安裝狀態與安裝後啟用選項。
* Site Manager 主控台重整站台詳細頁、操作分組與變更預覽介面；配對後依 Agent 回報功能預設開放可用操作，移除畫面上的 Level 術語與一次性 alert，改為持久的頁內狀態回饋。
* Site Manager 遠端操作失敗時會恢復按鈕狀態，並在操作區塊內保留可除錯的錯誤明細（action、job、Agent 回應摘要等），避免只顯示無法追查的頁首錯誤。
* Site Manager 匯入網站設定後會立即使用匯出字串內的 bootstrap passkey 嘗試配對 Agent；只有連線、安全檢查或版本能力不足時，畫面才會提示用「重新配對」恢復。
* Site Manager 新增 `wp mxp-site-manager export|import|pair|list` 指令；CLI 匯入預設會直接配對，也可用 `--skip-pair` 只保存站台設定，支援自動化佈署與救援流程。
* Site Manager Agent 驗證 Hub 簽章時會鎖定目前站台的配對 credential，避免同一 Hub 管多站時誤用其他站台較新的密鑰而讓遠端操作回 403。
* Site Manager Dashboard 改用專屬 `MXPSiteManager` 前端設定物件，避免其他管理頁腳本覆寫共用 `MXP` nonce 後造成「登入」等 AJAX 操作出現錯誤驗證。
* Site Manager 站台列表新增「移除」操作，會先確認再刪除 Hub 端保存的站台設定與配對憑證。
* Site Manager Level 2 預檢會保留原始 payload 並用該 payload 執行確認，避免畫面重繪後 select 重置造成啟用、停用、更新操作的 confirmation token 驗證失敗。
* Site Manager 外掛更新、啟用、停用改為表格式批次操作；可勾選多個外掛，一次預檢、一組確認後依序執行。
* Site Manager 變更操作表格補上明確的功能矩陣說明、列尾「加入批次」按鈕、已選數量與「預檢並準備執行」主按鈕，避免只看到下拉選單卻不知道如何執行。
* Site Manager 操作結果改為可讀表格與摘要，並在預檢、批次結果、錯誤回饋產生後自動聚焦到對應區塊，避免使用者執行後還停在原畫面找不到結果。
* Site Manager 的 Inventory / Refresh Snapshot 回饋改為專用可讀摘要：以卡片呈現 WordPress、PHP、DB、Agent、外掛/佈景數量、更新狀態、WP-Cron、檔案修改、時區與語系，並列出實際可更新項目，不再把 `plugins.items` / `themes.items` 物件陣列或英文 action key 直接塞進欄位。
* Site Manager 狀態同步與維護工具按鈕保留原本卡片結構，執行中只更新主標與說明，不再把按鈕內容壓成純文字；快照資料庫版本改用 `$wpdb->db_version()` 正確擷取。
* Site Manager 變更操作新增 WordPress.org 外掛安裝：輸入 slug 後先做 Level 2 預檢，確認後才安裝，並可選擇安裝後立即啟用。

= 3.6.10 =

* Feedback Reporter 載入 Painterro 後會還原既有 `window._`，避免 Painterro 內含的 Lodash 4 覆蓋 WordPress admin 依賴的 Underscore，造成媒體庫 `_.contains is not a function` 並讓特色圖片無法選取。

= 3.6.9 =

* Feedback Reporter 儲存 log、webhook 與匿名 IP hash/rate limit 時，改為只在 `REMOTE_ADDR` 符合可信代理 CIDR 後解析 Cloudflare / reverse proxy client IP header；可信 Cloudflare CIDR 會從官方 `ips-v4` / `ips-v6` 文字清單抓取並以 transient 快取，抓取失敗時回退內建清單；預設支援 Cloudflare `CF-Connecting-IP`，並在 Cloudflare Pseudo IPv4 overwrite 模式下改用 `CF-Connecting-IPv6` 保留真實 IPv6，避免直接請求偽造 `X-Forwarded-For`；匿名回報現在也會保存解析後的完整 IP 供濫用追蹤，且該 IP 會隨已設定的第三方 webhook 一併送出。
* Feedback Reporter 前台回報 modal / editor / controls 強化 CSS 隔離，避免站台主題覆寫按鈕、標題 pseudo element、表單控制項與回報卡片樣式。
* Feedback Logs 後台列表修正長 Trace ID、URL、檔案路徑與 webhook 文字撐破欄位的問題，改用固定表格寬度、水平捲動與欄內斷行。

= 3.6.8 =

* Feedback Reporter 的 Slack incoming webhook 不再送出 Block Kit image block；截圖與錄影仍保留在文字欄位與「開啟 Log」入口，避免 WordPress.com、Cloudflare、WAF、登入保護或靜態檔案策略阻擋圖片 URL 時造成 Slack 回 `invalid_blocks` 並讓整包通知失敗。
* Discord webhook 維持 multipart attachment 上傳截圖檔案的既有行為，不受此調整影響。

= 3.6.7 =

* Feedback Reporter 新增可選匿名前台回報：設定 `MDT_FEEDBACK_REPORTER_ALLOW_ANONYMOUS=true` 後，未登入訪客可使用同一套截圖、標註與錄影流程送出回報；匿名路徑使用短效 challenge、同站 Origin/Referer 驗證、honeypot、IP/UA/path rate limit、較小的預設檔案上限，且後台不對匿名訪客顯示。
* 匿名模式第一版即支援錄影回報（`MDT_FEEDBACK_REPORTER_ANON_ALLOW_VIDEO` 預設 true），預設限制為 20 秒 / 15 MiB，截圖預設 2 MiB；log 會標記 `anonymous` 使用者並保存 IP hash，不在匿名 log 中保存完整 IP。
* Feedback Reporter 修正前台與後台回報入口的捲軸鎖定：開啟回報模式視窗時改用可還原的 scroll lock 保留原視覺位置，避免 WordPress 後台因 `overflow:hidden` 被瀏覽器重設到頁面頂端。
* 所有 modal、錄影 popup 與送出完成流程改用 prevent-scroll focus，關閉或選擇截圖時會還原原始 scroll position，確保後續 Browser Screen Capture / SnapDOM fallback 都從使用者當下的 viewport 進行。

= 3.6.6 =

* Feedback Reporter 在支援且安全的瀏覽器環境中優先使用 Browser Screen Capture API，並採用接近線上會議的螢幕/視窗/分頁分享選擇器；需要包含 DevTools 或瀏覽器外框時可選整個螢幕或視窗，使用者取消或瀏覽器不支援時才回落到 SnapDOM/DOM 截圖。
* 新增錄製短片回報模式：支援 MediaRecorder 的安全桌機瀏覽器會開啟獨立錄影控制器，可選擇分頁、視窗或螢幕錄影，預設最長 60 秒；原頁跳轉不會中斷錄影，錄影中顯示倒數與停止按鈕，使用者可提前結束；送出時會附上錄影檔與封面截圖，後台 Feedback Logs 可預覽影片。不支援或彈窗被阻擋時會回落到頁內錄影/截圖流程。
* Discord / Slack webhook 會盡量使用一致的詳細資訊：使用者描述、頁面、SEO、回報者、角色、裝置、請求資訊、Console errors、Log、Screenshot、Video；Slack 使用 Block Kit + mrkdwn 欄位與可用時的截圖 image block，Video 欄位使用錄影檔案的站點完整 URL，方便內部通知直接點開；Apache/LiteSpeed `.htaccess` 會配合允許圖片/影片媒體檔直連並保留 JSON log 阻擋。
* 標註編輯器改成只縮放 CSS 預覽，實際 canvas 保留原始截圖像素；預設截圖上限提高到 3840×8192、檔案上限提高到 5 MiB，改善文字與細節模糊問題。
* Feedback Reporter viewport 截圖保留 client-side 資源 URL 正規化：對同站台的 www/non-www 圖片、`srcset`、inline style 與 computed background/mask image，改用目前頁面的 origin 讓 SnapDOM 直接讀取，避免常見跨 host alias 的 CORS/dataURL 失敗與截圖破碎。
* 保持不走預設後端圖片 proxy；真正第三方且未提供 CORS 的資源在 SnapDOM fallback 仍受瀏覽器安全模型限制，可用 Browser Screen Capture、來源端 CORS、上傳或貼上截圖 fallback。

= 3.6.5 =

* Feedback Reporter Logs 列表新增截圖縮圖，詳細頁新增大型截圖預覽；圖片透過後台權限與 nonce 保護的 `admin-post.php` endpoint 讀取，保留既有私有 log 目錄保護。
* 修正 WordPress.org Test Preview 藍圖：先安裝並啟用 `mxp-dev-tools`，再啟用 Feedback Reporter 子外掛，避免 Playground 在外掛尚未安裝時執行 `activatePlugin` 造成 `Plugin file does not exist`。

= 3.6.4 =

* 修正 Feedback Reporter 捲動頁面的 viewport 截圖：以暫存 viewport 舞台擷取目前畫面，並把 fixed/sticky 元素依實際視窗座標重疊，避免 DDEV 固定底部操作列在桌機與手機截圖中位移或遮蓋錯誤。
* 移除標註視窗中的「貼上截圖」按鈕；保留 Ctrl/⌘+V paste 事件與「上傳截圖」fallback，避開瀏覽器 Clipboard API 權限不一致造成的空按鈕體驗。

= 3.6.3 =

* 修正 Feedback Reporter 自動截圖範圍：截圖前不再先鎖定頁面捲動，並以目前 viewport 捲動位置裁切，避免回報內容誤抓頁面頂端。
* 新增截圖取代功能：標註視窗可上傳 PNG/JPEG/WebP，或在支援的瀏覽器按 Ctrl/⌘+V 從剪貼簿貼上圖片。
* 強化替代截圖流程的 RWD 介面、圖片尺寸壓縮、格式檢查與錯誤提示，讓桌機、手機與不同瀏覽器都有檔案上傳 fallback。

= 3.6.2 =

* Feedback Reporter 啟用子外掛後預設可直接回報並保存本機 log/截圖；`MDT_FEEDBACK_REPORTER_ENABLE=false` 仍可覆寫關閉。
* Feedback Logs 頁面新增 webhook 設定提醒：未設定時顯示通知，已設定時顯示目前通知類型與 host。
* 新增 Slack incoming webhook 自動偵測與 `MDT_FEEDBACK_REPORTER_WEBHOOK_FORMAT=slack`，使用 JSON + Block Kit 送出摘要與本機 log/截圖路徑。
* 新增 WordPress Playground `assets/blueprints/blueprint.json`，支援 WordPress.org 外掛頁即時預覽。
* 移除外部服務依賴說明段落。

= 3.6.1 =

* 更新 Feedback Reporter vendored SnapDOM 至 `3.2.0`。
* 確認 SnapDOM 3.2.0 與現有截圖流程相容：新增 ESM 動態載入 fallback，維持 `snapdom(target, options)`、`toBlob()`、viewport clip、ignore selector 與遮罩流程可正常運作。
* 強化 Feedback Logs 後台檢視頁：重要資訊分卡片顯示、webhook 狀態 badge、補送/刪除操作、Raw JSON 與手機版 RWD 呈現。

= 3.6.0 =

* 新增 `Dev Tools: Feedback Reporter - Mxp.TW` 子外掛，支援前台與後台登入用戶截圖、標註、填寫描述與 webhook 回報。
* 新增 `MDT_FEEDBACK_REPORTER_*` 常數設定：啟用狀態、後台低干擾入口、webhook、HTTPS/憑證嚴格度、role/user ID 限制、截圖大小、遮罩 selector、rate limit、log 保留天數與檔案數上限。
* 新增本機 JSON log + screenshot 檔案薄紀錄與每日清理機制；管理員可從「工具 → Feedback Logs」讀取檔案型回報紀錄、檢查 webhook 送出狀態、手動補送 webhook，並刪除紀錄；移除子外掛時預設刪除 log。
* 強化 Feedback Reporter 送出流程：後端在 webhook 前重新壓縮超限截圖，並將截圖頁面的 SEO meta/canonical/Open Graph/Twitter/H1/JSON-LD 型別摘要一併寫入 log 與 webhook。

= 3.5.9 =

* 調整網域到期檢查的 observed host 行為：預設不再自動記錄 HTTP_HOST，可用 `MDT_DOMAIN_EXPIRY_OBSERVE_HOSTS` 啟用。
* 新增 observed host 180 天保留規則、獨立檢視頁與刪除操作，避免非主要網域直接出現在控制台。

= 3.5.8 =

* 新增網域到期檢查資訊的註冊商、註冊日期、網域狀態、DNSSEC 與 Name Server 等基本細節。
* 調整網域到期通知文案，改用「已進入到期前提醒」並加入註冊商資訊，方便確認續約平台。

= 3.5.7 =

* 調整網域到期檢查資訊顯示完整主機名稱，避免子網域被簡化為主網域。
* 調整網域到期通知規則，僅通知 home_url / site_url 類型來源，純 observed_host 不寄送通知。

= 3.5.6 =

* 調整網域到期檢查資訊的後台文案，移除不易理解的英文術語。

