iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
AI 自動化

用 AI Agent 打造你的產品使用手冊產線系列 第 13

[Day 13] 產線實作 6:遮蔽敏感資訊

  • 分享至 

  • xImage
  •  

前面五天做的事情,某種程度上都是「品質問題」:元件抓不到、畫面不穩、框畫歪了、圓標擋到東西,最壞的結果是手冊看起來不夠專業。今天這一篇的性質比較不一樣,如果沒處理好,是有可能會出大事的。

哪些東西不能印進手冊

會不小心跟著截圖一起流出去的東西,種類比想像中多:授權金鑰、裝置序號、API token、內網伺服器位址、客戶名稱、真實錄影畫面裡拍到的人臉。這些東西一旦印在要交給客戶或第三方的手冊裡,就不是排版問題,而是實質的資訊外洩。

範例 App 的「系統設定 → 授權與裝置」區塊就是照這個情境設計的,三個欄位全部都是不該出現在手冊裡的東西:

完全沒有遮蔽的授權區塊,金鑰、伺服器位址、裝置序號一清二楚

順帶一提,這一整塊是 role=admin 才會渲染的,操作員登入時根本不存在於 DOM 裡。要拍到它得先照 Day 09 的做法注入 role (i.e. 這個敏感資訊是特定權限的人才看得到)。

三種遮蔽模式

處理敏感資訊大致有三種模式,適用場合不太一樣:

  • 色塊 (box):直接用實心色塊蓋住整個區域。最安全,因為底下的東西完全不會透出來,但也最醜、資訊量損失最多。
  • 模糊 (blur):讓讀者看得出「這裡原本有東西、大概是什麼長度與形狀」,但看不清楚內容。
  • 替換 (replace):把內容換成一組格式正確但完全虛構的假資料,例如把真實序號換成 AB-1234-XXXX-0000

三種各套一個,長出來是這樣:

同一塊區域,三個欄位分別套上色塊、模糊、替換三種模式

這裡想特別講的是「替換」。一般直覺會覺得「替換」只是「比較好看」的選項,但在使用手冊的場景,它常常是最合適的那一個。手冊的目的是教使用者「這個欄位該填什麼」,如果整條塗黑,讀者就不知道這裡期待的輸入長什麼樣子 (是純數字?還是有固定分段格式?)。換成一組格式正確的假資料,可以同時滿足「不外洩」與「讀者知道該填什麼」兩件事。

反過來說,色塊很適合當預設值,反正有疑慮就先全部遮起來就對了XD

在截圖之前調整 DOM

跟 Day 11 的標註一樣,遮蔽也不碰截圖的像素,而是在按下快門之前先把 DOM 動一動,截圖時一起拍進去。設定檔裡就是一個 redact 陣列:

{
  "screenshot": "settings-license-01.png",
  "redact": [
    { "testid": "license-input" },
    { "testid": "license-server-ip", "mode": "blur" },
    { "testid": "license-serial", "mode": "replace", "text": "AB-1234-XXXX-0000" }
  ]
}

三種模式對應到三種完全不同的手法:

const mode = rule.mode ?? 'box'

if (mode === 'box') {
  // 量好座標,稍後交給疊層畫實心色塊
  boxes.push((await locator.boundingBox())!)
} else if (mode === 'blur') {
  await locator.evaluate((el) => { el.style.filter = 'blur(6px)' })
} else {
  await locator.evaluate((el, text) => { el.value = text }, rule.text)
}

色塊之所以走疊層而不是直接把元件塗黑,是因為疊層蓋的是「畫面上那塊矩形」,跟元件內部是文字、圖片還是 canvas 無關,一套寫法全部通用。

遮蔽層跟 Day 11 的標註層是兩層獨立的疊層,順序上有個小地方要注意:遮蔽層的 z-index 要比標註層低一階。兩層都設成一樣的話,就會變成看後面誰蓋誰,圓標有機會被色塊吃掉。分好層之後,遮蔽與標註可以在同一張圖上共存:

遮蔽與標註並存:三個欄位都遮好了,圓標仍然完整露出

真人影像

如果畫面裡會拍到真人 (例如監控串流),處理方式有三種:換掉影像來源、事後人工打馬賽克、取得肖像使用同意。

推薦的是第一種,而且它跟 Day 09 是同一件事:串流畫面本來就該用 page.route() 換成固定的 fixture 圖,換的時候順手挑一張不含真人的圖就好,從源頭上就不會拍到人臉。

selector 找不到目標時,必須讓 build 失敗

這是今天最重要的一段。

假設某次改版把 license-input 改名成別的名字,或整塊搬到別的頁面,設定檔裡的 redact 規則就找不到目標了。如果實作上選擇「找不到就跳過」,產出會是這樣:

selector 過期之後,後面兩個欄位照常遮蔽,授權金鑰卻原封不動地露在外面

後面兩條規則照常生效,看起來像是有在運作,只有第一個欄位原封不動——而且整個過程不會有任何錯誤訊息。這種產出如果沒有人工審稿,會一路混進交付物裡。

所以 redact 的規則找不到目標時,唯一正確的處理是中止整個 build:

if ((await locator.count()) === 0) {
  throw new Error(
    `redact 找不到目標:${rule.selector}\n` +
      `  遮罩沒有被套用,敏感資訊會原封不動留在截圖裡,因此中止整個 build。`,
  )
}

經驗分享

1. blur 半徑太小等於沒遮

模糊的強度是連續的,這代表它有一個「看起來有遮、其實讀得出來」的灰色地帶。下面這張圖上面那欄是 blur(2px),下面那欄是 blur(6px)

blur(2px) 的授權金鑰仍然可以辨識,blur(6px) 才真的看不出來

blur(2px) 的金鑰其實還讀得出來,而且手冊的截圖通常是 deviceScaleFactor: 2 拍的,放大看更清楚。順帶一提,如果改用馬賽克 (像素化) 而不是高斯模糊,對規律的等寬字元其實有機會被還原回去,所以真正機敏的東西 (金鑰、憑證) 還是直接用色塊最乾脆,模糊留給「只是不想給人看,但外流也不至於出事」的東西。

2. 不要為了省事就把敏感畫面拍進來

前面提到說,授權區塊是注入 role=admin 才會出現的。也就是說,比「遮得好不好」更前面的一個問題是:

這一章真的需要拍這個畫面嗎?

如果手冊的讀者是操作員,那最好的做法不是把授權區塊拍下來再遮好,而是根本不要注入 admin。遮蔽是不得不拍時的補救手段,不是拍攝範圍的許可證。

到這裡,一張時機、範圍、標註、遮蔽都正確的截圖就完成了,單點技術的部分告一段落。明天要把這六天的東西全部收攏進一份設定檔裡,用宣告式的方式描述完整的一本手冊。


上一篇
[Day 12] 產線實作 5:標號與標號說明
下一篇
[Day 14] 手工組裝產線 1:宣告式設定檔
系列文
用 AI Agent 打造你的產品使用手冊產線17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言