砍掉重練 #3:一個「很有隱私意識」的設計,差點抹掉公司的歷史
一個看起來很負責任的設計
事情從一個很正當的念頭開始:隱私。
當一個員工離職、帳號要被刪除,把他的個人資料留在系統裡好像不太對。所以我做了一個「刪除即匿名化」的設計:一旦刪除這個使用者,就把他的個人資訊抹掉,換成「已刪除使用者」,其中,也包括他的名字。
聽起來很有隱私意識,對吧?我當時也是這麼想的,還挺滿意自己考慮得很周到。
那個讓我涼掉的瞬間
問題在於,我這行的紀錄,每一筆都要記「這是誰做的」。某某某量了體重、某某某做了觀察、某某某執行了手術,這些紀錄裡的「記錄者」,靠的正是使用者的名字。
發現的那一刻,其實沒有預警。我只是在測試離職流程時,順手回頭查了一筆早先的體重測量紀錄,想確認資料看起來正常,結果那一欄「記錄者」,寫著「已刪除使用者」。
我愣了半秒,才意識到那不是系統的顯示錯誤,是我自己設計出來的功能,正在做它「該做」的事。
整個人涼掉。不是那種抽象的「這樣不太好」,是很具體的、胃往下沉的那種涼,因為我馬上想到:這不會只有這一筆。凡是這個帳號經手過的紀錄,全部都會是這樣。
我幾乎是立刻切回資料庫,開始一筆一筆算,這個帳號到底碰過多少筆紀錄、牽連多廣。算下去才發現,牽連的範圍比我第一時間想的還大,量測、觀察、手術紀錄,只要是他手上經過的,署名全部一起不見了。操作記錄只剩下「已刪除使用者」。
僥倖,但不是全身而退
事後回想,我還算幸運。這件事發生的時候,還沒有真的員工離職。我是在真正有人走之前,自己拿測試流程把這顆地雷先踩出來的。
如果晚一步,是等到真的有人離職才第一次跑到這段邏輯,那洗掉的就不是可以回頭補救的測試資料,而是真正、正式、已經進入稽核鏈的職員操作歷史。
但「僥倖」不代表「毫髮無傷」。因為系統是我自己天天在用的正式環境,我拿來測試的那個帳號,本身已經留下了一段時間的真實操作紀錄,不是憑空捏造的假資料。跑完那次測試刪除,這些是真的被洗掉的紀錄,署名是真的消失了。
要把名字寫回去,沒有一鍵復原這種東西。我得回頭翻備份和操作日誌,一筆一筆核對時間點、裝置、對應的操作內容,才能把「這一筆到底是誰做的」重新拼回去。中間有幾筆時間點很接近、記錄內容又相似,一時對不太起來,緊張了一下,深怕有筆對錯了、被我張冠李戴。
整個過程說起來有點狼狽,也有點荒謬:我因為怕自己的匿名化功能抹掉別人的身份,結果最後是靠著另一份紀錄,去救回被我自己親手匿名化功能洗掉的身份。
在合規的世界裡,歸屬不能被抹掉
如果這只是一間普通公司,也許沒那麼嚴重。但在一個要面對稽核、講究 GLP/21 CFR Part 11 的產業,這是重罪。
因為在這個世界裡,有一條鐵律:紀錄的「歸屬」,不能被事後抹掉。誰做的,就永遠是誰做的。
這不是為了「抓」誰,而是因為,當一筆紀錄連「是誰做的」都能被後來的操作改掉,那這筆紀錄還能信嗎?整個系統的可信度,就是建立在「歸屬不可竄改」這塊地基上的。
我為了「保護一個已離職員工的隱私」,差點把所有還在職員工的紀錄可信度,一起賠了進去。
我怎麼收窄它
發現之後,我趕緊把這個設計收窄。「隱私」和「可信度」不是二選一,它們該分層:
- 屬於「歸屬」的資料 —— 名字 —— 保留。因為它是紀錄可信度的一部分,不能動。
- 屬於「純個資」的資料 —— email、電話、組織、職稱 —— 才匿名化。這些拿掉不影響任何一筆歷史紀錄的署名,隱私也顧到了。
隱私要顧,但不能拿整間公司的歷史可信度去換。分清楚哪個是哪個,兩邊才能同時成立。
我從這一刀學到的三件事
- 「看起來很負責任」的設計,可能正在破壞一個沒注意到的地基。越是那種讓自我感覺良好的設計,越要多問一句:它會不會在別的地方悄悄挖走一塊基礎?
- 在合規領域,有些事的優先序跟直覺是相反的。直覺說「刪乾淨才安全」,但法規說「該留的歸屬一個都不能少」。接班若接到一個受管制的產業,這種「反直覺」會遇到很多,別用常識硬套。
- 最危險的坑,是不會報錯的坑,而且它未必會等準備好才發生。角色設計錯了、PDF 破版了,系統會用難用、難看提醒我。但這個坑不會,它安靜地運作,直到某天有人離職才爆出來。這次是我自己不小心先踩到、也自己修了;但它本來完全可能是先在一個真實員工身上發生,而我要到那時候才發現。這種坑,只能靠「多想一步」去防,不能靠僥倖去賭下一次還會這麼幸運。
當自己是那個做決定的人,就沒有人會在身後幫忙踩煞車。我得自己學會,在按下「刪除」之前,先想想那一刀會割到什麼。