跳轉到

安全政策設定(Security Policy)

功能群:系統管理|三層 RBAC 模型與角色權限基調先讀 功能群總覽 §2 / §5

事實基準:2026-08-29 從 FE src/views/security-policy/SecurityPolicyForm.vue + BE api/system_config/routes/security_policy_route.py / app/system_config/service/security_policy_app_service.py / infra/system_config/runtime_config.py + migration scripts/sql/2026-08-29-cm1423-security-policy-page.sql 掃出(CM-1423 為新頁,routes.json dump 早於本功能,端點與選單位置改以源碼與 migration 核實)

變更紀錄

日期 FR 變更
2026-08-29 CM-1423 首版:登入安全政策設定頁(強制 MFA/登入鎖定/密碼週期/憑證效期共七參數),含開啟 MFA 前的防鎖死守門(OTP 通道未就緒需明示確認)與 JWT 效期需重啟的如實提示

1. 功能描述

安全政策設定頁是全站登入規則的單一設定頁:強制兩階段驗證(MFA)開關、登入失敗鎖定、閒置停用天數、密碼有效期、登入憑證效期,共七個參數。

這些設定值早就存在system_configs 的 ROOT 租戶列、group='RUNTIME_CONFIG',自 FR-063.1g 起),登入流程每次都即時讀取——本頁補的是管理介面,不是新的機制。在此頁之前,客戶要改任何一項都只能請原廠下 SQL。無新增資料表

系統層全域一份設定,故無列表、無 uid、只有一張表單。

🔴 本頁最重要的性質:強制 MFA 是唯一一個「開錯就沒有人進得來」的設定。 驗證碼靠寄信送達,SMTP 沒設好時開啟 MFA,會讓包含操作者自己在內的所有帳號卡在登入第二關,且無法從任何 UI 救回(只能下 SQL)。頁面為此設計了三層防呆,見 §4

主要使用者:具 security-policy.* 能力的系統管理員(能力點授予對象比照 SMTP 伺服器設定,兩者同屬「系統設定」選單群)。

角色速覽

角色 一句話
security-policy.read 看得到本選單並讀得到政策與 OTP 通道就緒度
security-policy.update 可儲存政策(開啟 MFA 另有防鎖死守門,見 §4)
其他登入者 無此選單;直打 API 亦被 require_capability 擋下 403

1.1 功能總覽(本頁全部功能)

# 功能 說明 位置 詳述
1 載入既有政策 進頁 GET /system/security-policy 回填;非 404 的讀取失敗會鎖住儲存 整頁(onMounted §6.2
2 強制兩階段驗證開關 MFA_REQUIRED即時生效,不需重啟 「兩階段驗證」區 §4
3 OTP 通道就緒度顯示 進頁即顯示:就緒=綠色確認訊息;未就緒=紅色常駐警告(列出缺哪些欄位)+「前往郵件伺服器設定」按鈕 開關上方 §4
4 開啟 MFA 的風險確認框 「從關到開」且通道未就緒時,儲存前再過一次紅色確認框,確認後才帶 confirm_risk=true 儲存時 UC-SP-02
5 登入失敗鎖定次數 LOGIN_MAX_LOCK_COUNT,1–100 「登入與鎖定」區 §9.3
6 帳號鎖定時間 LOGIN_USER_LOCK_TIME,30–86400 秒。UI 用分鐘、BE 存秒 「登入與鎖定」區 §12 坑 3
7 閒置停用天數 LOGIN_INACTIVITY_THRESHOLD_DAYS,1–3650 「登入與鎖定」區 §9.3
8 密碼有效天數 CHANGE_PASSWORD_THRESHOLD_DAYS,1–3650 「密碼政策」區 §9.3
9 登入憑證效期 JWT_ACCESS_TOKEN_EXPIRES / JWT_REFRESH_TOKEN_EXPIRES,60–31536000 秒。改了要重啟服務才生效 「登入憑證有效時間」區 §12 坑 1
10 需重啟提示 憑證效期區常駐提示;存檔後若真的改到再 toast 一次(由 BE restart_required_keys 驅動,不在 FE 寫死) 該區塊 + toast §6.2
11 儲存政策 PUT,部分更新;無實際變更時不寫入也不留稽核 表單底部 UC-SP-01
12 離開頁面確認 快照比對(改回原值不算髒) 全域 §10
13 授權唯讀降級 useLicenseReadonly 命中時儲存鈕反灰並提示原因(不隱藏) 表單底部 §3

展開成 UC:UC-SP-01(儲存政策)、UC-SP-02(開啟 MFA 的防鎖死路徑)。載入、離開確認等為常規表單行為,不另展開。

2. Use Case

角色速覽

角色 一句話
security-policy.read 看得到本選單並讀得到政策
security-policy.update 可儲存政策(開 MFA 另有守門)
其他登入者 無此選單;直打 API 403

UC-SP-01 儲存登入政策

項目 內容
觸發 管理員改完欄位按「儲存」
前置 security-policy.update;進頁 GET 未失敗(否則儲存被鎖,見 §4)
主流程 ① FE 驗數值格式 → ② PUT /system/security-policy整包unknown=EXCLUDE 容忍唯讀欄位回送)→ ③ app service 逐鍵比對現值、只挑真的變了的鍵 → ④ 逐鍵寫入 ROOT 租戶列 → ⑤ 寫稽核事件 6110 → ⑥ 回傳 changed_keysrestart_required
例外 數值非整數 → 400 SECURITY_POLICY_400001;超出範圍 → 400 SECURITY_POLICY_400002不靜默夾成邊界值);寫入失敗 → 400 SYSTEM_CONFIG_SHARED_WRITE_FAILED
結果 除 JWT 效期外即時生效(登入流程每次重讀);改到 JWT 效期則 restart_required=true,FE 額外 toast 提示需重啟

無實際變更時不寫入:七個欄位原封不動按儲存,回 changed_keys=[]、不寫 DB、不留稽核——避免「按了儲存但什麼都沒改」污染稽核軌跡。

UC-SP-02 開啟強制 MFA(防鎖死路徑)

項目 內容
觸發 管理員把「強制兩階段驗證」由關切到開並按儲存
前置 同 UC-SP-01
主流程 ① 進頁時 BE 已回 otp_readiness,未就緒則畫面常駐紅色警告 → ② 按儲存時 FE 判定「從關到開 + 通道未就緒」→ 跳確認框 → ③ 使用者按「我了解風險,仍要開啟」→ 帶 confirm_risk=true 送出 → ④ app service 同樣判定,confirm_risk 為真才放行
例外 未帶 confirm_risk 且通道未就緒 → 412 SECURITY_POLICY_412001,資料不寫入
結果 開啟後下次登入即要求 OTP(即時生效,無需重啟)

只擋「開啟」方向:關閉 MFA 是解除鎖死的動作,任何情況下都不被擋住——這是刻意的,且已實測驗證。

不是硬性禁止,是要求明示確認:客戶可能正在用驗證器 App(TOTP,不需收信),或明知風險而刻意為之,一律禁止會變成擋路。

視覺慣例:判斷框(黃菱形)=分支條件;橙框=擋下;紅框=錯誤終點(標 error code);綠框=成功終點;虛線=可選路徑。

3. 權限矩陣

系統管理群整體基調見 _overview §5。本頁與 Log 轉發設定 同屬「兩個端點都有能力點守門」的頁(對照 SMTP 伺服器設定LDAP 設定 的寫入端點僅 @jwt_required)。

操作 FE 判定 BE 強制 BE 檢查位置
進入本頁 ui_routes 可見性(security-policy.read,requirement=ALL public.route_capabilities
讀取政策 有選單即可 require_capability("security-policy.read") api/system_config/routes/security_policy_route.pySecurityPolicyRoute.get
儲存政策 hasCap('security-policy.update') → 否則全欄位 disabled require_capability("security-policy.update") 同上(SecurityPolicyRoute.put
開啟 MFA(通道未就緒) 確認框攔一次 app service 層擋(412),非只在 route app/system_config/service/security_policy_app_service.py::update_policy
授權唯讀期間 useLicenseReadonly().writeDisabled() 把儲存鈕反灰並顯示原因 由授權層另行守門 src/composables/useLicenseReadonly.js

守門走 FR-048 統一授權守門軸④ capability,route decorator 形式——主體域守門只看「你是誰」,不必先 resolve 資源,故允許放在 route 層(decorator 內部委派 DI 注入的 guard service,route 本身不碰 session)。

兩個能力點皆 is_platform = false:這是租戶級系統設定頁,落地部署版的客戶系統管理員必須自己改得動;設成平台層會被 trg_role_capabilities_platform_guard 擋住而下放不了(同 CM-1283 SMTP/LDAP 下放的理由)。授予對象在 migration 中以「誰已持有 smtp-config.update動態推導,不硬編 role id。

授權豁免security-policy 列在 common/authz/license.pyINFRASTRUCTURE_MODULES(CM-1409 模式)。判準是「這一項會出現在報價單上嗎」——不會,沒有人單買「兩階段驗證模組」。不豁免的話落地版會把整頁標成未授權而從選單消失。

4. 狀態機與前置條件

本頁無業務狀態機(單一設定組覆蓋式更新),前置條件集中在防鎖死守門數值範圍

條件 效果 出處
「MFA 從關到開」且 otp_readiness.ready=false 且未帶 confirm_risk 412 SECURITY_POLICY_412001,不寫入 security_policy_app_service.py::update_policy
同上但帶 confirm_risk=true 放行(明知風險而為之,如已改用 TOTP) 同上
關閉 MFA 任何情況都不擋——關閉是解除鎖死的動作 同上(turning_mfa_on 只判 True 方向)
不碰 MFA、只改其他欄位 不受防鎖死守門影響 同上(守門條件含 "MFA_REQUIRED" in payload
整數欄位非整數 400 SECURITY_POLICY_400001 同上(_coerce_for_write
整數欄位超出範圍 400 SECURITY_POLICY_400002——拋錯而非靜默夾成邊界值 同上(_INT_RANGES
payload 帶 DEFAULTS 以外的鍵 忽略(schema unknown=EXCLUDE 擋一層,app service 再擋一層) 同上
無任何實際變更 不寫入、不留稽核,回 changed_keys=[] 同上
進頁 GET 失敗且非 404 FE configLoadFailed=true,之後按儲存直接 toast 擋下——此刻表單顯示的是預設值而非實值,存下去等於用預設覆蓋正確設定 SecurityPolicyForm.vue(比照 LogForwardingForm / StorageConfigForm
改到 JWT_*_EXPIRES restart_required=true設定值已寫入 DB,但要重啟服務才生效 RESTART_REQUIRED_KEYS

OTP 就緒度的判定範圍(重要,不可誇大)get_otp_readiness() 檢查的是ROOT 的 SMTP 設定存在且 host/port/from 三欄齊全不是「真的寄得出去」——真試寄需要收件人且有數秒延遲,不適合擋在存檔路徑上。故三層文案措辭一律是「可能寄不出」。

reason 意義
smtp_not_configured 尚未設定郵件伺服器
smtp_incomplete 設定不完整,missing_fields 列出缺哪幾欄
smtp_check_failed 讀取 SMTP 設定時發生例外——視為未就緒(檢查本身壞掉不可以被解讀成「一切正常」,那正是防呆要防的方向)

5. UI 設計

版面骨架(單卡片表單、四個區塊,無 tab、無列表):

┌──────────────────────────────────────────────────────────┐
│ 安全政策設定                                              │
│ ℹ 除「登入憑證有效時間」需重啟外,其餘儲存後立即生效        │
├──────────────────────────────────────────────────────────┤
│ 兩階段驗證                                                │
│  ⚠ 郵件伺服器尚未就緒…(未就緒時常駐紅色)[前往郵件設定]   │
│  ✓ OTP 信件通道正常(就緒時綠色)                          │
│  [開關] 強制兩階段驗證(MFA)                              │
├──────────────────────────────────────────────────────────┤
│ 登入與鎖定                                                │
│  登入失敗幾次後鎖定帳號 [ 3 ]                              │
│  帳號鎖定時間(分鐘)   [ 15 ]                             │
│  多久沒登入就停用帳號(天)[ 180 ]                          │
├──────────────────────────────────────────────────────────┤
│ 密碼政策                                                  │
│  密碼有效天數 [ 90 ]                                       │
├──────────────────────────────────────────────────────────┤
│ 登入憑證有效時間                                          │
│  ⚠ 此區設定需重新啟動服務後才會生效(常駐)                 │
│  登入憑證有效時間(秒) [ 300000 ]                          │
│  換發憑證有效時間(秒) [ 720000 ]                          │
├──────────────────────────────────────────────────────────┤
│                                      [ 儲存 ]             │
└──────────────────────────────────────────────────────────┘

📸 實機截圖待補(亮色模式)。待補清單:OTP 就緒(綠訊息)、OTP 未就緒(紅警告 + 缺欄清單)、開啟 MFA 的確認框、存檔後的需重啟 toast、無權限時全欄位反灰。

狀態呈現

  • loading 期間以 LoadingStatesize="page")取代整張表單。
  • 頁首固定一則說明訊息,明講「除憑證效期外其餘即時生效」——不讓使用者誤以為全部都要重啟,也不讓他以為憑證效期會即時生效
  • OTP 就緒時也顯示綠色確認訊息:如實告知狀態,不是只有壞的時候才講。
  • 憑證效期區塊的「需重啟」提示由 BE 的 restart_required_keys 驅動、不在 FE 寫死——BE 改了畫面自動跟上。
  • 儲存鈕反灰時以 tooltip 顯示原因(無權限/授權唯讀/讀取失敗),不隱藏按鈕
  • 存檔後以 BE 回的實際結果回填再拍快照,不用送出的 payload 拍——否則 BE 沒照收的欄位會被誤認為已存。

6. API 規格

Envelope:成功 {"code": 1, "data": …}、失敗 {"code": 0, "msg": "…"}(見專案 CLAUDE.md Response Format)。

6.1 總清單(本頁呼叫的全部 endpoint)

分類 Method + Path 說明 完整規格
讀取 GET /api/1.0/system/security-policy 讀政策 + OTP 就緒度 + 需重啟鍵清單 §6.2
儲存 PUT /api/1.0/system/security-policy 部分更新(未帶的鍵沿用現值) §6.2

為什麼不走既有的泛用 system config 端點:泛用端點是 {group, key, value}逐列 CRUD——一頁七個參數就要打七次 PUT,且前端得自己知道每列的 uid。RUNTIME_CONFIG 語意上是「一組政策」而非「一堆設定列」,故給它一支 group 粒度的讀寫端點,內部再拆成逐 key 寫入。

路徑刻意不放在 /system/config/<group>/<key> 底下——那是動態規則,會把這條路徑吃掉。

無 uid、無列表端點:系統層單一設定語意,路徑不帶識別碼。

6.2 讀取 / 儲存

GET 回應:

欄位 型別 說明
policy dict 七個政策鍵的目前生效值
otp_readiness object {ready, reason, missing_fields},見 §4
restart_required_keys string[] 固定為兩支 JWT 效期鍵

policy 的值來源與登入流程完全一致get_runtime_config():內建預設 ← DB 覆寫),不直接讀 DB 列——否則 DB 沒有那一列時頁面會顯示空白,而登入流程實際上正照著內建預設在跑,兩邊對不上。

PUT 請求:七個政策鍵皆選填(部分更新),另有 confirm_risk(boolean,預設 false)。

  • schema 的數值欄位一律用 Raw 而非 Integer型別轉換與範圍檢查集中在 app service,避免 schema 與 service 兩處各有一套驗證、日後改一邊漏一邊。schema 只負責「哪些 key 可以進來」。
  • unknown = EXCLUDE:FE 會把 GET 回來的整包(含 otp_readiness 等唯讀欄位)原樣回送,嚴格模式會整包 400 掉。
  • confirm_risk 不是政策值本身,不會被寫進 DB(app service 只認 DEFAULTS 內的鍵)。
  • route 用 schema.load() 而非 use_kwargs 注入:本端點是部分更新,需要區分「沒帶這個 key」與「帶了 None」,kwargs 展開後兩者都是 None。

PUT 回應:GET 的全部欄位,另加 changed_keys(本次真的變了的鍵)與 restart_required(本次是否改到需重啟的鍵)。

Error code

Code HTTP 意義
SECURITY_POLICY_400001 400 數值格式不正確
SECURITY_POLICY_400002 400 數值超出允許範圍
SECURITY_POLICY_412001 412 OTP 通道未就緒時要開啟強制 MFA,需帶 confirm_risk
SYSTEM_CONFIG_SHARED_WRITE_FAILED 400 寫入 ROOT 設定列失敗

7. 前端檔案地圖(compliance-manager-fe/)

檔案 角色
src/views/security-policy/SecurityPolicyForm.vue 唯一頁面元件(表單、防鎖死警告與確認框、分鐘↔秒換算)
src/config/router/index.js 路由 /system/security-policy(name=security-policy
src/config/api/api.js SECURITY_POLICY: getUrl('/system/security-policy')
src/config/locales/i18n/{zh-tw,en}/security-policy.json 頁面文案(中英)
src/config/locales/i18n/{zh-tw,en}/menu.json 選單名與說明
src/composables/useLicenseReadonly.js 授權唯讀降級(共用)

8. 後端檔案地圖

檔案 角色
api/system_config/routes/security_policy_route.py 兩支端點;require_capability 守門;把 confirm_risk 從 HTTP 邊界轉譯進 app service
api/system_config/serializers/security_policy.py request / response schema
app/system_config/service/security_policy_app_service.py 核心:讀寫政策、OTP 就緒度、🔴 防鎖死守門、數值驗證、稽核
infra/system_config/runtime_config.py DEFAULTSget_runtime_config()(登入流程與本頁共用的讀取器)
infra/system_config/system_config_root_reader.py ROOT 租戶列的讀寫器(read_root_config_value / write_root_config_value
common/authz/license.py INFRASTRUCTURE_MODULES 豁免清單
common/code/error_code.py 三支 SECURITY_POLICY_* error code
common/enum/event_code.py SECURITY_POLICY_UPDATED = 6110
di_containers/system_config/system_config_containers.py DI wiring
scripts/sql/2026-08-29-cm1423-security-policy-page.sql 能力點 seed/授予/ui_routes 選單登記/route_capabilities 綁定

9. DB

9.1 資料表總清單(本頁讀寫的全部表)

用途 讀/寫
config.system_configs 政策值本體(ROOT 租戶列,group='RUNTIME_CONFIG');另讀 group='SMTP' 判 OTP 就緒 讀寫
public.capabilities security-policy.{read,update} 兩個能力點 讀(migration 寫)
public.role_capabilities 能力點授予 讀(migration 寫)
public.ui_routes 選單列(/system/security-policy,掛系統設定群 sort=15) 讀(migration 寫)
public.route_capabilities 路由↔能力點綁定 讀(migration 寫)
public.system_logs 稽核事件 6110

無新增資料表——政策值沿用既有的 system_configs

9.2 核心設定鍵

七個鍵全部位於 config.system_configsROOT 租戶列group='RUNTIME_CONFIG',值為 JSONB。

預設 允許範圍 生效方式
MFA_REQUIRED 環境變數 MFA_REQUIRED,否則 false boolean 即時
LOGIN_MAX_LOCK_COUNT 3 1–100 即時
LOGIN_USER_LOCK_TIME 900(秒) 30–86400 即時
LOGIN_INACTIVITY_THRESHOLD_DAYS 180 1–3650 即時
CHANGE_PASSWORD_THRESHOLD_DAYS 90 1–3650 即時
JWT_ACCESS_TOKEN_EXPIRES 300000(秒) 60–31536000 需重啟
JWT_REFRESH_TOKEN_EXPIRES 720000(秒) 60–31536000 需重啟

MFA_REQUIRED 的預設值刻意吃環境變數:三環境 .env 都明寫此項,若改成硬預設 false,會讓「有設 true 的環境」在 DB 未 seed 時行為悄悄改變。優先序:DB RUNTIME_CONFIG > 環境變數 MFA_REQUIRED > False

上界不是技術限制而是防呆:把 JWT 效期設成 10 秒、把鎖定次數設成 0,效果等同把系統弄壞,而使用者多半是手誤而非本意。

10. 頁面邏輯與資料對應

畫面元素 資料來源 備註
七個欄位初值 GETpolicy 值來自 get_runtime_config()(DB 覆寫 ← 內建預設)
OTP 警告/確認訊息 GETotp_readiness reason 決定文案,missing_fields 決定「缺哪幾欄」
需重啟提示 GETrestart_required_keys 不在 FE 寫死
「這次是不是從關到開」 進頁時記下的 MFA 實際狀態(mfaWasOn 不能用畫面上的值判——使用者已經把開關撥開了
鎖定時間欄位 LOGIN_USER_LOCK_TIME ÷ 60 換算只在進出口各做一次(toForm / toPayload
儲存後回填 PUT 回應的 policy 用 BE 實際結果,不用送出的 payload
離開確認 快照比對 改回原值不算髒

11. 背景行為與外部依賴

  • 登入流程是唯一的消費端MFA_REQUIRED 等鍵由登入服務在每次登入時即時讀,故改了立刻生效、不需重啟。這是本頁「多半是接線不是新做」的原因。
  • JWT 效期是例外:由 flask_jwt_extended服務啟動時讀進 app.configcore/app_factory.py 啟動期 app.config.update(get_runtime_config())),改 DB 不影響已跑起來的進程。
  • 寫入落點是 ROOT 租戶列:與讀取端同一列。寫進呼叫者自己的租戶列會變成「存成功但沒人讀」的靜默失效(CM-1283 的教訓)。
  • 稽核:政策異動寫 system_logsevent_code=6110,帶操作者與 changed_keys(改 MFA 開關等於改變全站登入強度,屬稽核關切點)。
  • 能力點分流表RUNTIME_CONFIG → security-policy 已補進 CM-1331 的 GROUP→能力點對照表。本頁走專屬端點,但這組列仍可能被泛用 by-uid 端點碰到;不掛進表會 fallback 到誰都沒有的 system_config.*,變成「專屬端點改得動、泛用端點永遠 403」的兩套門鎖。

12. 邊界情況與已知坑

  1. JWT 效期改了不重啟就沒生效:設定值確實已寫進 DB,但跑著的進程仍用舊值。頁面已常駐提示+存檔後 toast,但沒有任何機制強制重啟——落地版請配合 guidant restart
  2. 🔴 落地版 OTP 的 Redis 缺口(本頁的防呆擋不到):jedi-mfa 存驗證碼用的 Redis client 只認舊的 JSON 格式 REDIS_SECRET,不認主專案 .env 現行的平鋪格式(REDIS_USER / REDIS_PASSWORD),.env.sample 已有警語。安裝版的 guidant.env 沒有 REDIS_SECRET 這個 key——若該部署的 Redis 有設密碼(正式部署應該要有),jedi-mfa 會連不上 Redis → 驗證碼存不進去 → 開了 MFA 就登不進系統,症狀與 SMTP 沒設好一模一樣。本頁的防呆檢查的是郵件伺服器設定,不檢查 Redis,擋不到這個。 屬 installer 範圍,補起來之前落地版不建議開啟強制 MFA

    DEV 之所以測得通是環境剛好寬鬆而非設定正確:DEV 的 .env 根本沒有 REDIS_SECRET,jedi-mfa 以「無帳密」連 Redis,而 DEV 那台 Redis 恰好允許免帳密連線。

  3. 鎖定時間 UI 是分鐘、DB 是秒:改 FE 時注意換算只在 toForm / toPayload 各做一次,不要散在各處。直接讀 DB 值比對畫面數字會對不上。
  4. OTP 就緒度不等於「寄得出去」:只檢查 SMTP 設定齊全(host/port/from),沒有真試寄。文案措辭一律是「可能寄不出」,不可改成斷言式說法。
  5. 離開頁面時即使未編輯也可能跳「尚未儲存」確認框:既有 LogForwardingForm 實測同樣行為,屬該頁型樣共通問題,非本頁引入,另案處理。
  6. ui_routes 那一列不可少:缺了不只是選單看不到,FE 的 hasCap() 也拿不到能力(capability 掛在路由節點下回給 FE),整頁會反灰。FR-068 T-1 曾漏過一次。

13. 開發與驗證

  • 跑起來:BE python main.py(port 8000,log 在 log/app.log);FE 在 compliance-manager-fe/ 起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload)。
  • 測試帳號:需具 security-policy.* 能力(DEV 上為 Administrator 角色;比照 SMTP 設定頁的權限範圍)。帳號見 memory reference_dev_login / .env(憑證不寫入本文件)。
  • 導航路徑:登入 → 側選單「系統設定」→「安全政策設定」(/system/security-policy)。
  • 前置資料:DEV 需已套 scripts/sql/2026-08-29-cm1423-security-policy-page.sql該 migration 只套 DEV,STG/POC 未動。
  • 驗防鎖死的方式:暫時弄壞 SMTP 設定(清掉 host)→ 進頁應顯示紅色警告 → 開 MFA 存檔應回 412 且確認 DB 未被寫入 → 帶 confirm_risk 應成功 → 關 MFA 應任何情況都放行。
  • E2Ecompliance-manager-test/ repo(Cucumber + Playwright);本頁尚無 feature 檔。
  • 相關文件:同群設定頁對照 SMTP 伺服器設定LDAP 設定Log 轉發設定;站內操作紀錄查詢見 操作日誌