A
約 8 分鐘閱讀

AI 風險管理措施檢核系統開發紀錄 — FastAPI + React 的權限、版本控制與離線部署

因為工作上的需求,我需要把一套 AI 風險評估流程整理成系統:當一個政府單位想把 AI 用進工作流程時,不能只問「好不好用」,也得先想清楚它可能影響誰、風險在哪裡、出了狀況怎麼處理。

於是,我把原本需要來回確認的一套評估流程,整理成一個讓機關承辦人可以一步步填寫、管理者可以掌握進度的系統。

一開始我以為,這大概就是「問卷加上後台」。真正做下去才發現,最花時間的其實不是把畫面做出來,而是把那些看似一句話就能講完的規則,變成每個人都看得懂、系統也守得住的流程。

這件事從哪裡來

人工智慧基本法在 2026 年 1 月 14 日公布施行;其中第 19 條要求政府使用 AI 執行業務或提供服務時,應進行風險評估並規劃因應措施。於是,原本需要人工來回確認的事情,被整理成一段可追蹤的流程。

系統裡的評估大致沿著這個順序往下走:先盤點應用情境,再辨識與評估風險、思考應對方式,最後做整體判定。第 16 條也提醒我們,風險分類與管理規範會隨著實務持續演進;而第 4 條的「問責」原則,則讓版本與紀錄從一開始就不能只是附加功能。

系統真正要解的事

技術上,這是一個前後端分離的網頁系統:使用者在前端填寫與查看資料,後端負責驗證、處理規則與保存紀錄,資料庫則負責把該守的底線守好。

實作工具會隨專案而變,但這套系統的核心一直沒變:讓評估流程有跡可循,也讓每個人只在自己該負責的範圍內操作。

權限不是「能不能按按鈕」而已

專案中期,我們重新整理了權限設計。原本的做法太細碎,遇到問題時,光是回答「為什麼這個人可以、另一個人不行」就要翻很久。

後來把思路收斂成兩件事:

這套系統共有五種角色:

角色 管得到誰的資料 對問卷能做什麼
系統管理員 全平台 建立、查閱、改草稿、刪除整份情境
平台觀察員 全平台 只能看,連別人的草稿都看得到,但改不了
部會管理員 本部會+下屬機關 建立、查閱、改草稿(範圍內不限本人所建)、刪草稿
機關管理員 本機關 建立、查閱、改草稿(範圍內不限本人所建)、刪草稿
一般使用者(承辦人) 自己的,加上同機關同事已送出的(只能看) 建立、修改、刪除自己的草稿

這個拆法聽起來樸素,卻讓事情清楚很多。舉例來說,系統可以區分誰能管理、誰只能查看;同樣是能修改的人,也不一定能碰到所有資料。

另外,我們把「草稿可以調整、正式送出後保留紀錄」當成基本原則。這不只避免誤改,也讓後續追查時不會只剩下一個被覆蓋掉的結果。

還有一個很容易被忽略的地方:權限異動後,不應該等到使用者下次登入才生效。因此系統在每次需要確認身分的操作時,都會以帳號目前的狀態為準。登入憑證是方便使用者的工具,不該成為舊權限繼續生效的理由。

版本要留下,但不能長出兩個「下一版」

評估內容送出後,難免還是會需要更新。問題是,直接覆蓋會讓舊資料消失;全部複製又容易變成一團找不到脈絡的紀錄。

我們最後採用的是「每次更新都產生新版本、舊版本保留」的方式。使用者能看到演變過程,也能知道這次調整是接在哪一份資料之後。

這裡最有趣的坑,是兩個人剛好同時更新同一份資料。兩邊都以為自己正在建立下一版,結果可能都想取到同一個版本號。

這種事不能只靠前端提醒或程式碼裡的「先看一下再存檔」。最後要讓資料庫擔任守門員:把「同一份資料不能有重複版本」變成它本身會檢查的規則。有人慢了一步,就清楚告知他重新整理後再操作,而不是默默留下兩份看起來都對、其實彼此衝突的資料。

這也讓我再次確認:重要的規則,最好不要只存在某一段應用程式碼裡。

題目會變,資料也要跟得上

評估題目不是做完一次就永遠不動。欄位會增減、選項會調整、說明也會改寫;如果每改一題就得大幅調整資料結構,維護成本很快會失控。

因此,系統使用較有彈性的方式保存一份評估的作答內容,讓題目調整不必牽動整張資料表。不過彈性從來不是免費的:資料庫知道這是一包結構化資料,卻不一定知道使用者畫面上的每一格代表什麼。

我曾經遇過一個很典型的例子:使用者每一欄都沒有填超過限制,送出時卻被系統判定內容太長。原因不是他真的寫太多,而是系統不小心量到了整包打包後的資料,而不是使用者眼前的單一欄位。

修正後留下的學習很簡單:驗證規則要對齊使用者理解的單位。使用者看到的是一個欄位,系統就應該以那個欄位來判斷,而不是拿儲存格式來為難他。

為了讓舊資料不會因為題目改版而「長錯樣子」,每次發布新題目時,也會保留當時的題目版本。日後回頭看舊紀錄,仍然能用當時的脈絡理解它。

刪除一筆資料,往往不只是刪除一筆資料

在需要保留責任歸屬的系統裡,「刪掉帳號」或「刪掉資料」通常不是真的按一下就消失。

資料和建立者、組織、歷程之間常常有關聯。如果處理得太隨意,可能會留下找不到負責人的紀錄,讓資料變成孤兒;處理得太嚴格,又可能讓已經不再使用的資料把帳號或組織卡住,刪不掉。

這個專案讓我很深刻地體會到:要先定義「什麼資料必須保留歸屬」、「什麼情況可以暫時抽離關聯」,再決定刪除流程怎麼走。資料庫的約束也提醒我,系統不只看最後結果,有時候連更新過程中的半成品狀態都要合理。

聽起來有點龜毛,但這正是資料不會在多年後變成一團謎的原因。

在沒有外網的環境部署

這個專案也讓我第一次比較完整地處理受限環境的部署。數位發展部的部署環境沒有對外網路,所以不能走一般的部署流程,把程式丟上去再在主機上抓套件、建立映像;每次更新都得先在本地把 image 建好、打包成可傳遞的檔案。

接著,在 shell 裡透過 SCP 把檔案傳到主機,再用 PuTTY 登入,載入預先建好的 image,並輸入 Docker Compose 指令把服務起起來。聽起來像是一連串很樸素的步驟,但每一步都得確認版本、檔案與服務狀態,少一個環節就可能讓正式環境還停在舊版。

這段經驗讓我更清楚:交付不只是「程式寫完」,還包含讓正確版本能在正確的環境穩定跑起來。對我來說,這也是這個專案很特別、學到很多的一部分。

有些問題,真的要上線才會遇到

開發環境順順的,不代表正式環境也會一模一樣。

這次的部署條件比較受限,讓我更重視兩件事:第一,發布流程要能明確確認「現在跑的是哪一版」;第二,跨環境的連線要把短暫中斷視為正常情況來面對。

有些連線問題不會直接跳出明確錯誤,而是看起來像使用者偶爾需要重試。後來從連線生命週期、服務等待時間與環境差異慢慢往回追,才把問題收斂下來。

這段經驗很像在提醒我:測試能幫忙抓到很多事,但它不是現場的替身。部署環境、網路條件與實際操作節奏,也都是產品的一部分。

資安設計,重點是少一點誤傷

上線前,我們也補了一些基本防護。不過我不想把這件事寫成一串設定清單,因為重點其實是思考方式。

例如,針對尚未登入就能使用的功能,防護措施要同時考量濫用風險與正常使用者,不該因為一個人的異常操作,害整個辦公環境的人都無法完成正常流程。

又例如,短效與長效的登入憑證不該用同一種方式保存。把不同風險的東西分開處理,才能在安全與使用體驗之間找到比較實際的平衡。

安全不是加一個開關就結束,而是持續問自己:這條規則保護了誰?又可能誤傷誰?

AI 幫我加速,但沒有替我做決定

這個專案的開發過程中,我有使用 Claude Code 協助撰寫與整理程式。不過越做越覺得,AI 最有價值的地方不是「一下子生出很多程式」,而是讓我能更快把想法做成 PoC,讓我跟同事能夠快速測試並且馬上調整。

我的習慣是把功能切小:做完一段就測,發現規則不對就回頭修,再往下一步走。權限、版本這類事情尤其不能只看畫面正常;還要刻意去測「本來就不該成功」的情境。

AI 可以幫忙加快實作、補測試情境、整理重複工作,但它不會替你釐清需求,也不會替你承擔「這個規則到底合不合理」的判斷。那部分還是得由人慢慢想、慢慢補。

最後留下的兩個提醒

先想清楚不能被破壞的規則,再做功能。 例如版本不能衝突、正式紀錄要可追溯、資料不能莫名失去歸屬。這些底線越早講清楚,後面的設計就越不容易一直補洞。

把「為什麼」也寫下來。 有些做法看起來只是多繞一步,背後往往是某次踩過的坑。留下背景與取捨,比只留下程式碼更能幫到未來接手的人。

結語

回頭看,這個專案最有趣的地方,不是哪個框架或哪段程式寫得多漂亮,而是把一堆抽象的規則,慢慢翻譯成每個人都能使用的流程。

從「誰可以做什麼」,到「資料改了以後怎麼留下脈絡」,再到「上線後怎麼穩定地運作」,每一題都不是只有唯一答案。能做的,是把當下的取捨想清楚、寫清楚,並且讓系統有能力守住它。

還有就是,想不到在我的職涯中竟然有機會把自己開發的專案部署到 gov 網址上,應該也算是某種成就達成了哈哈哈😆


站內相關文章: