feat(diagnostics): crypto 健檢 + backup 目錄探測 + 15 個 usermeta 欄位(PR-G)

- Crypto::is_key_derivable()(A v3.3.2):AUTH_KEY / SECURE_AUTH_SALT 皆缺
  時回 false,讓金鑰推導優雅短路
- wp tmdo doctor 新增兩項健檢:
  · backup 目錄 HTTP 可及性探測(200 = 紅旗並附 nginx 設定建議,
    403/404 = OK,0 = 離線時退回檢查 .htaccess)(A v3.1.9)
  · crypto 金鑰可推導性(缺常數時警告 notifier secrets 會以明文儲存)
- doctor_callback 呼叫簽章 3 參數 → 1 參數(A v3.0.3 修復)。**ABI 變更**:
  AddOn 註冊的 callback 若依賴 rows / full_name 需自行調整
- Member_Fields::register_admin_prefs_group() 由 7 欄擴到 22 欄(A v3.1.4),
  補上 wp_user_level / show_welcome_panel / wp_persisted_preferences /
  wp_user-settings / community-events-location 等 15 個 WP 原生 usermeta,
  這些先前全部落在 wp_usermeta
- capture_before_value 預設 true → false(A v3.1.5):每次受管寫入省一次
  DB read。**行為變更**:需要 value_before 的消費者(audit log)要
  add_filter( 'wpdo_capture_before_value', '__return_true' ) 明確開啟

unit 451 / integration 398 GREEN

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
2026-07-31 06:11:52 +08:00
parent 56d534619e
commit d6c1540444
4 changed files with 168 additions and 10 deletions
@@ -497,6 +497,88 @@ final class TMDO_Member_Fields {
'type' => 'textarea',
'label' => 'Comma-separated dismissed pointer IDs',
),
array(
'key' => 'wp_user_level',
'type' => 'integer',
'label' => 'WP legacy user level (0-10); written by WP on every role change',
),
// WP admin-UI prefs written on first dashboard visit or explicit user action.
array(
'key' => 'show_welcome_panel',
'type' => 'text',
'label' => 'Dashboard welcome panel visibility (true/false/1/0)',
),
array(
'key' => 'wp_persisted_preferences',
'type' => 'textarea',
'label' => 'Block editor persisted preferences (JSON blob)',
),
array(
'key' => 'nav_menu_recently_edited',
'type' => 'text',
'label' => 'ID of nav menu most recently edited',
),
array(
'key' => 'wp_dashboard_quick_press_last_post_id',
'type' => 'integer',
'label' => 'Post ID from last Quick Draft save',
),
array(
'key' => 'edit_page_per_page',
'type' => 'integer',
'label' => 'Rows-per-page in Pages list table',
),
array(
'key' => 'edit_post_per_page',
'type' => 'integer',
'label' => 'Rows-per-page in Posts list table',
),
array(
'key' => 'edit_hp_listing_per_page',
'type' => 'integer',
'label' => 'Rows-per-page in hp_listing list table',
),
// Keys with hyphens: sanitize_column_name() strips hyphens entirely.
// community-events-location → communityeventslocation (column name)
// wp_user-settings → wpusersettings
// wp_user-settings-time → wpusersettingstime
// managenav-menuscolumnshidden → managenavmenuscolumnshidden
// metaboxhidden_nav-menus → metaboxhidden_navmenus.
array(
'key' => 'community-events-location',
'type' => 'textarea',
'label' => 'Dashboard community-events saved location (JSON); column: communityeventslocation',
),
array(
'key' => 'wp_user-settings',
'type' => 'text',
'label' => 'WP admin UI settings string; column: wpusersettings',
),
array(
'key' => 'wp_user-settings-time',
'type' => 'integer',
'label' => 'Timestamp when wp_user-settings was last written; column: wpusersettingstime',
),
array(
'key' => 'managenav-menuscolumnshidden',
'type' => 'text',
'label' => 'Hidden columns in nav-menus screen; column: managenavmenuscolumnshidden',
),
array(
'key' => 'metaboxhidden_nav-menus',
'type' => 'text',
'label' => 'Hidden meta-boxes on nav-menus screen; column: metaboxhidden_navmenus',
),
array(
'key' => 'dismissed_no_secure_connection_notice',
'type' => 'text',
'label' => 'Admin dismissed "no secure connection" notice (1/empty)',
),
array(
'key' => 'meta-box-order_product',
'type' => 'textarea',
'label' => 'Meta-box order on WC Products screen (serialized); column: metaboxorder_product',
),
)
);
}