老師的說明

老師這次分享的是一套用 OpenAI Agents API(測試版)規劃出來、可以治理的海報製作系統。系統自訂了 sandbox(以 OpenAI client 建出來的虛擬平台),能管理、預覽、監控,並且有運行管理與稽核管理兩塊。老師接著把整套系統轉成 agent skill framework,可以配置到 GPT work、Claude cowork,或是自建的 agents 平台。他強調的重點是:這是一個可以監控、可以管理的 LLM client sandbox VM。整套系統用 Sonnet 5.5 開發。

「我沒有使用 xhigh,只使用 High。」

編者註:xhigh、High 是模型的推理強度檔位。

「全自動化配置 skills workflow 讓他跑一整個晚上,完成九個完整系統範例,以及錄影與教案文件以及海報製作。(我有一套完整的 skill framework)」

YouTube 影片縮圖 老師分享的影片(在 YouTube 開啟) 08 古典後臺儀表板與畫廊式海報圖庫 youtu.be/MkgkPaPgyNQ・艾立克程式設計學院
稽核講義封面:古典後臺架構解密
稽核講義封面:〈古典後臺架構解密:打造無懈可擊的儀表板與圖庫〉,副標「從縱深防禦、效能優化到破壞式驗證的企業級後端實踐」,共 12 頁,對應第 01~03 課。
技術包講義封面:Agent Skills 架構與系統藍圖
技術包講義封面:〈古典書院海報平台 Agent Skills 架構與系統藍圖〉,副標「9 大核心模組解構、端到端協作與安全護欄指南」,共 15 頁,對應第 04~07 課。封面上的英文小字標註圖中未能辨識。
課程地圖

投影片上的字在手機上比較小,每一張圖都可以點一下放大。

第一份講義・後台稽核管理(12 頁)
第二份講義・Agent Skills 技術包(15 頁)加資料庫架構圖

第 01 課・稽核講義 p.02–04

權限隔離:同一個入口,三道關卡

古典書院海報平台的畫廊,有兩種人在用同一個服務:一般使用者只想看自己做的海報,管理者要看全站。第一課先看講義怎麼回答它的核心問題:同一個服務入口,要怎麼確保資料與權限絕對隔離。

兩種視野:個人畫廊與全站監控

個人畫廊(範圍 own)與全站監控(範圍 all)對照
圖 稽核 p.02 個人畫廊(範圍:own)對照全站監控(範圍:all)。

左邊是個人畫廊,範圍標成 own:一般使用者只看得到自己的作品,講義強調絕對隱私,就算有人在網址後面硬加 ?user=admin 這種越權參數,也會被無視。右邊是全站監控,範圍標成 all:管理者看全局統計並處理異常,而且每個動作都強制留下稽核紀錄。中間那塊提出整份講義的核心問題,答案在下一張圖。

三道關卡:縱深防禦

攔截不合法請求的三道關卡
圖 稽核 p.03 攔截不合法請求的三道關卡:路由層、服務層、查詢層。

講義的答案是在請求進來的路上放三道關卡。第一關在路由層,用 Depends(require_admin) 擋下沒有授權的身分;第二關在服務層,再確認一次角色是不是 scope="all",就算路由層那一關被誰不小心拿掉,服務層還是會丟出 GalleryDenied。第三關在查詢層,範圍是 own 時,系統直接在 SQL 裡綁死 PosterJob.user_id = viewer.id,前端傳來什麼篩選條件都不採用。這種做法叫縱深防禦:任何一道單獨失效,另外兩道還守得住底線。

存取控制矩陣與破壞式驗證

存取控制矩陣:匿名者、一般會員、管理者對各路由的回應碼
圖 稽核 p.04 存取控制矩陣:三種身分打各條路由,各自得到什麼回應。

這張矩陣把「誰打哪條路由會得到什麼回應」列成表。沒登入的匿名者得到 303 或 401(303 是轉址、401 是未授權),登入了但不是管理者的一般會員得到 403,只有管理者拿到 200。圖上列了三條路由,另外還有 17 條以上的敏感路由,都在同一張矩陣的自動化測試看守之下。講義另外提到「破壞式驗證」:測試時故意把某條路由的保護拿掉,看測試會不會真的報錯,用這種方式證明測試本身抓得到問題。

路由匿名者一般會員管理者
/admin/gallery303 / 401403200
/api/admin/stats303 / 401403200
/admin/jobs/{id}/cancel303 / 401403200
其他 17 條以上敏感路由303 / 401403200

上表是把 p.04 的矩陣照圖重打成文字,方便手機閱讀與搜尋。

3道關卡(路由/服務/查詢)
3種身分(匿名/會員/管理者)
20+條 /admin 敏感路由受矩陣看守

本課重點

  • 同一個畫廊服務分成 own(只看自己)與 all(全站)兩種範圍,使用者傳來的越權參數一律無效。
  • 路由層、服務層、查詢層各守一道,任何一道失效,其他兩道仍擋得住。
  • 最底層的查詢直接把擁有者條件寫進 SQL,不聽前端的篩選。
  • 每一條 /admin 路由都有自動化矩陣測試,而且測試會故意拆掉保護來確認它抓得到。
01 / 07

第 02 課・稽核講義 p.05–08

效能優化與儀表板口徑

畫廊要快,儀表板上的數字要可信。這一課看講義怎麼用縮圖與查詢技巧把畫廊變輕,又怎麼把成功率、平均處理時間這些數字的算法先定義清楚。

縮圖策略:列表只讀縮圖

無縮圖災難對照非同步縮圖策略
圖 稽核 p.05 無縮圖災難(The Raw Image Trap)對照非同步縮圖策略(Async Thumbnailing)。

左邊是沒做縮圖的下場:一頁 12 張原圖、每張約 2 MB,一次要傳 24 MB,畫廊一打開就把伺服器的頻寬與記憶體吃光。右邊是講義的做法:背景 Worker 先把圖轉成 RGB,縮到長邊 360px,存成 82% 品質的 JPEG,再寫進資料庫的 BLOB 欄位;12 張縮圖每張約 20 KB,一頁不到 250 KB。圖底的流程是:列表只讀縮圖,使用者點擊放大時,才走 /gallery/{id}/image 去載入原圖。

查詢的三個小心思

畫廊查詢的優化藝術:延遲載入 BLOB、智慧分頁防呆、無縫相容舊資料
圖 稽核 p.06 畫廊查詢的優化藝術:三段程式碼各帶一個設計。

第一,一頁 12 筆的清單查詢,刻意不撈 content 與 thumb 這兩個大型二進位欄位(延遲載入 BLOB),翻頁時就不會搬大檔。第二,page = min(max(1, page), pages) 讓使用者輸入 page=99 這種超出範圍的頁碼時,自動收斂到最後一頁,不會白畫面,也不會 500 錯誤。第三,舊資料沒有縮圖時,現場補做並存回資料庫(Lazy Generation),第二次讀取就生效,新舊資料不用另外搬遷。

儀表板:定義決定真相

儀表板設計:成功率與平均處理時間的嚴謹口徑
圖 稽核 p.07 成功率與平均處理時間,各自附上「嚴謹口徑」。

成功率的公式是「已完成 ÷(已完成+失敗)」,取消與排隊中的工作不算進去,因為它們還沒有結果,或是被人為中斷,不該拉低系統真實的能力指標;沒有資料時顯示「—」而不是「0%」,免得被誤讀成全部失敗。平均處理時間只算成功的工作,公式是「完成時間 − 最後一次認領時間」,也就是扣掉排隊時間,失敗的耗時不混進來。圖上的 82.4% 與 24.5s 是版面上的示例數值,講義沒有註明是否為實測。

趨勢圖與失敗原因

每日工作量趨勢與失敗原因分佈
圖 稽核 p.08 每日工作量趨勢(Time-Series Aggregation)與失敗原因分佈。下方副標的英文字形在原圖就有瑕疵,不影響內容。

上半張是每日工作量長條圖(圖上畫 Oct 01 到 Oct 05)。SQL 的 GROUP BY 只回傳「有資料的日期」,沒工作的那一天整根長條會消失,時間軸就出現斷層,所以講義讓 Python 應用層動態補 0,圖上 Oct 03 的 0 就是補出來的。下半張是失敗原因分佈,有 Connection Error、Timeout、Data Invalid、Processing Fail 四類,其中 Connection Error 最多。長條用紅色斜線填滿,是無障礙設計(a11y)的做法:不能只靠顏色區分,色覺障礙的人也要看得出失敗狀態。

本課重點

  • 縮圖由背景 Worker 預先做好存進資料庫,列表一頁從 24 MB 降到不到 250 KB,原圖只在點開時載入。
  • 清單查詢不撈大型二進位欄位;超出範圍的頁碼收斂到最後一頁;舊資料缺縮圖就現場補做。
  • 成功率只算「已完成與失敗」,平均處理時間只算成功的工作,口徑先寫清楚數字才可信。
  • 沒有資料顯示「—」,沒有工作的日期由應用層補 0,失敗狀態不只靠顏色(紅色斜線)。
02 / 07

第 03 課・稽核講義 p.09–12

稽核紀錄與架構總覽

稽核是這份講義的收尾:一筆紀錄由什麼組成、什麼動作該記、哪些邊界要特別小心,最後把前三課拼成一個整體。

一筆稽核紀錄的解剖

稽核紀錄:Actor、Action、Target、Result 四欄與只增不改守則
圖 稽核 p.09 稽核紀錄的四個欄位與「只增不改」守則(The Anatomy of an Audit Log)。

每一筆紀錄由四個欄位組成。Actor 存的是操作者名稱的快照,管理員日後就算被刪除,紀錄裡還留得住當時是誰,不會變成沒有主人的空值。Action 寫入前要對照固定清單,拼錯的動作名稱會直接丟 ValueError,不會悄悄進資料庫。Target 指出被影響的資源(圖上舉例是海報 #15),Result/Detail 則精確標記 ok 或 denied。最底下的核心守則是只增不改(Append-Only):系統不提供修改或刪除的 API,對 /admin/audit 送 PUT、PATCH、DELETE 一律回 405。

決策樹:什麼該記,什麼不該記

稽核決策樹:找不到目標不寫、允許則執行並寫入、拒絕仍寫入
圖 稽核 p.10 決策樹:管理者送出動作之後,依序問「找得到目標嗎」「業務規則允許嗎」。

目標找不到(404)就不寫紀錄,避免製造垃圾雜訊。找得到、業務規則也允許(200),就執行動作並寫入稽核,結果標 OK。找得到但業務規則不允許(409,例如想取消已經完成的工作),拒絕動作,但仍然寫入稽核,結果標 Denied。講義的看法是:「管理者想做但被系統擋下」這件事本身,就是很有價值的資安追查線索。圖底橫幅的最後一句在「拒絕,也」處被截斷,後半句圖中文字未能辨識,這裡不推測。

三個敏感操作的邊界

敏感操作的邊界考量:檢視與下載、設定遮罩、強制撤銷
圖 稽核 p.11 敏感操作的邊界考量:檢視 vs. 下載、設定遮罩、強制撤銷。

第一格談「檢視」與「下載」:管理者只是看別人的圖不記錄,免得日誌被淹沒;下載別人的圖才記錄,因為那等於把敏感資料帶出系統。第二格談設定遮罩:設定頁面絕對唯讀,金鑰欄位(SECRET_FIELDS)只顯示「已設定」,並用破壞式測試確認畫面真的印不出金鑰字串。第三格談強制撤銷:管理員可以一鍵撤銷使用者的 Session,系統更新資料庫的 revoked_at、寫一筆稽核,並讓前端 Cookie 立刻失效。

架構總覽:互為掩護的生態系統

架構總覽:Gallery、3-Gate Defense、Audit Watcher、Optimized Storage 與架構師檢查表
圖 稽核 p.12 架構總覽:一個互為掩護的生態系統,右下是 The Architect's Checklist。

最後一張把前面拼成一個整體:Gallery(畫面)、3-Gate Defense(Route/Service/Query 三道關卡)、Audit Watcher(稽核監看)與 Optimized Storage(優化過的資料庫)互相連接。右下的架構師檢查表有四項:畫面與資料的權限絕對隔離、統計數字有極端防呆、效能優化放在資料儲存的時機、每一個越權意圖都被不可逆地記錄。左下的結語是:好的後台系統不只是資料的 CRUD,它用嚴格的口徑傳達真相,用縱深防禦與稽核建立信任,再用底層優化撐住使用體驗。

本課重點

  • 稽核紀錄固定四欄:Actor(名稱快照)、Action(白名單)、Target、Result/Detail(ok 或 denied)。
  • 稽核只增不改,連 PUT、PATCH、DELETE 都直接回 405。
  • 找不到目標不記;被業務規則擋下的動作照樣記成 Denied,因為被擋下本身就是線索。
  • 看別人的圖不記、下載別人的圖才記;設定頁唯讀且金鑰遮罩;撤銷 Session 要寫稽核並讓 Cookie 失效。
03 / 07

第 04 課・技術包 p.02–05+資料庫架構圖

資料庫與 Skill 技術包全景

第二份講義換個角度:前三課那套海報平台,怎麼讓 AI Agent 也能操作,而且守同一套規則。這一課先看全景:Skill 與網站共用同一個後端、資料存在哪、技術包怎麼分層、Agent 怎麼少讀文件、九個模組長什麼樣子。

Skill 是專案的「第二個呼叫端」

9 大 Skills 橋樑連接 Agent 自然語言需求與專案 Services 層
圖 技術包 p.02 左邊是 Agent 的自然語言需求,中間是 9 大 Skills 橋樑,右邊是專案 Services 層與 15 張 SQLite 表。

講義的重點是「單一事實來源」:Skill 不是另外寫一套實作,而是專案的「第二個呼叫端」,授權、雜湊、冪等、稽核這些規則自動和網站一致,腳本絕對不直接寫 SQL。介面雖然不同,後端是同一個,所以沒有重複的核心邏輯,安全性也只需要顧一份。

資料庫:SQLite 的四個區域

數據典藏的神經樞紐 SQLite:身分與授權區、AI 記憶區、數位資產區、稽核監控區
圖 資料庫架構圖 老師另外貼的一張投影片:〈數據典藏的神經樞紐(SQLite)〉。

這張圖把資料表分成四區:身分與授權區(users、email_verifications、auth_sessions、connector_connections)、AI 記憶區(agent_sessions、agent_events、sandbox_instances)、數位資產區(source_files、prompt_templates、poster_jobs,以及存圖片的 poster_images,標示為 BLOB),還有稽核監控區的 audit_logs。底部的「架構亮點」說,背景 Worker 採用「短交易」機制,等外部 API 產圖的那段時間,絕不鎖死資料庫寫入;白話講,就是資料庫交易只在真的要寫入的瞬間才開,不會一邊等外部服務回應一邊握著交易不放。

對不上的小地方:這張圖畫出 12 張表,p.02 寫的是 15 張,差的三張圖中沒有標出來;各區之間交錯的箭頭也沒有文字說明,這裡不推測。

三層架構與規模

技術包三層架構:Skill 知識層、腳本層、專案層
圖 技術包 p.03 嚴格垂直階層,單向依賴:Skill 知識層、腳本層、專案層。

技術包由上往下分三層。第一層是 Skill 知識層(.claude/skills/poster-*),放 SKILL.md(入口與路由)、workflows/(怎麼做)、references/(規則)。第二層是腳本層(scripts/*.py),處理命令列參數、護欄(--yes、--live)與輸出的隱私遮蔽。第三層是專案層(poster_app),有 services/、repositories/、models/ 與 app.db(WAL 模式)。設計鐵律是相依方向嚴格向下:腳本層取代了原本 Web Router 的位置,規則只有一份。

9個 Skills
32支腳本(5,750 行)
50份 workflows
19份 references

漸進式載入:每次只讀需要的那幾份

漸進式參照:觸發、路由、參照、執行四步驟
圖 技術包 p.04 用「重試失敗的工作」走一遍:觸發、路由、參照、執行。

Agent 收到「重試失敗的工作」,先比對各 Skill 的 description,載入一份 SKILL.md;再依路由表只讀 workflows/cancel-or-retry-job.md;workflow 提示需要確認狀態機時,才讀 references/job-lifecycle.md;最後呼叫 scripts/jobs.py retry 產出結果。傳統作法是一次載入 69 份文件,Token 成本高,也容易產生幻覺(對照上一張,50 份 workflows 加 19 份 references 剛好是 69)。漸進式的結果是 Agent 每次只負擔 1 份 SKILL、1 份 workflow,必要時再加 1 份 reference。

九個模組:一個地基加八顆衛星

Hub-and-Spoke 架構圖:01 foundation 與其他八個 skill
圖 技術包 p.05 Hub-and-Spoke 架構圖:地基與衛星(The Foundation and Satellites)。

中心是 01 foundation,由 poster_env.py 當共用啟動器,管環境與資料庫;外圈八個是 02 accounts、03 sources-prompts、04 agent-session、05 sandbox、06 connector、07 image-jobs、08 admin-console、09 release。核心定律是 foundation 必須與其他 skill 放在同一個目錄下,它是系統運作的「絕對地基」,決定腳本要操作哪一個專案範例與資料庫。

模組在後面哪幾頁看得到
01 foundation技術包 p.05(共用啟動器)、p.10 第 1 條泳道(init_db 建庫)
02 accountsp.10 第 1 條泳道(register alice 註冊驗證)
03 sources-promptsp.06(檔案存取防護網、四層提示詞)、p.10 第 2 條泳道(allow/select/compose)
04 agent-sessionp.07(Agent Session 狀態機)
05 sandboxp.07(Sandbox 環境狀態機)
06 connectorp.08 右側(Connector MCP 護欄)
07 image-jobsp.08(Worker 生命週期)、p.10 第 3 條泳道、p.12(images.py verify)
08 admin-consolep.09(獨立狀態檢視)、p.12(取消/重試、匯出圖片)
09 releasep.09(Release Preflight)、p.12(backup.py reconcile)

這張對照表是編者依各頁圖上出現的名稱整理的,講義本身沒有附這張表。

本課重點

  • Skill 與網站共用同一個 Services 層,Skill 腳本是專案的「第二個呼叫端」,不直接寫 SQL。
  • 資料庫是 SQLite,分身分與授權、AI 記憶、數位資產、稽核監控四區;背景 Worker 用短交易,不會在等外部 API 時鎖住寫入。
  • 技術包分 Skill 知識層、腳本層、專案層三層,相依只往下;規模是 9 個 Skills、32 支腳本、50 份 workflows、19 份 references。
  • Agent 漸進式載入,每次只讀 1 份 SKILL、1 份 workflow、必要時 1 份 reference,不一次吞 69 份文件。
  • 九個模組以 01 foundation 為地基,必須和其他 skill 放在同一個目錄。
04 / 07

第 05 課・技術包 p.06–08

防護網、狀態機與 Worker

進到模組內部:Agent 讀使用者檔案要過哪幾關、提示詞怎麼組、Session 與 Sandbox 各有什麼狀態,以及 Worker 把一張海報做出來的生命週期。

檔案存取防護網與四層提示詞

使用者檔案存取防護網三道關卡與四層提示詞組合模型
圖 技術包 p.06 左:使用者檔案存取防護網;右:四層提示詞組合模型。圖上有一處標示重複:左上角也標成「4.」,括號寫 Params,與右下角「3. 工作參數」重複,應是圖上誤植,這裡以 1 到 4 的順序為準。

Agent 要讀使用者提供的來源文件,不是想讀哪就讀哪,要過三道關:Gate 1 檢查路徑(resolve_source_path,防越界);Gate 2 檢查文件(read_document,確認存在且是 UTF-8);Gate 3 比對白名單(select_for_user,管理者核可)。三關都過,結果才會變成 source_files,存內容快照與 SHA-256。右邊的提示詞由四層疊成:1. 系統規則、2. 風格範本、3. 工作參數、4. 驗收條件,正中央是來源快照。底下的安全提醒:憑證與密碼只存雜湊(scrypt/SHA-256);提示詞發布(publish --yes)是不可逆行為,產出帶不可逆的版本號與雜湊。

兩個狀態機:Agent Session 與 Sandbox

Agent Session 狀態機與 Sandbox 環境狀態機
圖 技術包 p.07 左:Agent Session 狀態機;右:Sandbox 環境狀態機,各附一則「破除迷思」。

Agent Session 平時在 idle(目前沒在做事)與 running 之間來回,一輪結束會落到 completed、failed 或 cancelled。講義特別「破除迷思」:工具失敗不等於整個回合失敗,idle 只代表現在沒在做事,成敗要看 last_outcome。Sandbox 環境從 pending 走到 connected,之後可能變成 disconnected 或 expired;它的狀態是「觀測值」,不是即時同步,要靠 refresh 向遠端重新觀測。底部的護欄提醒:用假網關(MOCK_OPENAI=true)時,遠端狀態只存在單一行程的記憶體,跨腳本呼叫無法追加或取消。

Worker 的圖像工作生命週期

Worker 圖像工作生命週期 JobRunner 四步驟與 Connector MCP 護欄
圖 技術包 p.08 左:Worker 圖像工作生命週期(JobRunner);右:Connector MCP 護欄。

Worker 做一件工作分四步:1. 認領(Claim,租約約 600 秒,先佔住資源);2. 呼叫圖像網關(Call,這段不持有資料庫交易);3. 驗證圖片(Validate,解碼並檢查尺寸);4. 寫入與回存(Commit,同一個交易裡改狀態並寫入 BLOB)。這和上一課資料庫圖講的「短交易」可以對照著看:等外部產圖的那段不握交易,只在最後一步一次寫完。底部的圍籬機制(Fencing)說:Worker 當機導致租約過期,下一輪由別的 Worker 接手;工作若被取消,已經完成的結果與檔案會被丟棄,確保資料一致。右側的 Connector 護欄,是 ChatGPT 請求進來時先過範圍守衛:documents:read、jobs:write、jobs:read。

本課重點

  • 使用者檔案要過路徑檢查、文件檢查、管理者白名單三關,才會變成帶 SHA-256 的內容快照。
  • 提示詞四層:系統規則、風格範本、工作參數、驗收條件,都以來源快照為核心;發布提示詞不可逆。
  • Session 的 idle 不代表成功,成敗看 last_outcome;Sandbox 狀態是觀測值,要 refresh。
  • Worker 四步:認領、呼叫網關(不持有交易)、驗證、同一交易內寫入;租約過期由下一輪接手,被取消的結果丟棄。
05 / 07

第 06 課・技術包 p.09–12

管理台、單一入口與責任分工

模組各自就位之後,要看它們怎麼接力:管理台怎麼看全局、上線前怎麼檢查與備份、一張海報從註冊到驗收經過哪些 Skill,以及三種下單來源怎麼收斂到同一個入口。

Admin Console 與上線前檢查

Admin Console 獨立狀態檢視與 Release Preflight 飛行前檢查與備份
圖 技術包 p.09 上:Admin Console 的四個獨立狀態儀表;下:Release Preflight 飛行前檢查與備份。

上半是四個獨立的狀態儀表:網站登入 Session、Agent Session、Sandbox 實例、海報工作(Jobs),儀表下方標著數量(圖上如 ACTIVE USERS 52、RUNNING 12/TOTAL 15、HEALTHY 8/TOTAL 8、PROCESSING 4/COMPLETED 200、FAILED 1,是版面上的示例數值)。黃框提醒:稽核日誌 audit_logs 只能新增,無法修改或刪除。下半是上線前流程:先跑 13 項 Preflight 檢查(含 HTTPS、密碼、空間,圖上 PASS 13/13),沒過就阻擋上線;通過後用 SQLite 線上 API 備份,輸出快照加資料夾與 manifest.json,最後立刻驗證備份。維護心法是「腳本比網頁嚴格」:網頁可能忽略錯誤的篩選條件,Admin 腳本遇到錯誤格式一律報錯(結束碼 2)。

泳道圖:從零到驗收的責任接力

Swimlane Sequence Diagram 四條泳道
圖 技術包 p.10 Swimlane Sequence Diagram:維護者/Agent 代表使用者 Alice,走過四條泳道。

圖中的維護者(或 Agent)代表使用者 Alice,依序走過四條泳道。Lane 1(Foundation & Accounts):init_db 建庫、register alice 註冊驗證。Lane 2(Sources & Prompts):allow 管理員白名單、select Alice 選定快照、compose 組合提示詞。Lane 3(Image Jobs):submit 提交佇列、worker_run once 產圖並寫入 BLOB。最後是 Admin & Release:gallery search 全站圖庫查驗、backup create 上線前備份、run_tests 驗收。講義的收束句是「每個 Skill 只負責專屬領域邏輯,組合成高度自動化的無縫生產線」。

三種來源,一個入口

收斂架構:網站表單、內建 Agent、ChatGPT 三種來源經唯一入口 JobService.create_job 進入佇列
圖 技術包 p.11 Convergence Architecture:The Single Indestructible Bottleneck(單一且堅不可摧的瓶頸)。

下單的來源有三種:網站表單(origin=web)、內建 Agent(內建工具,origin=agent)、ChatGPT(MCP 授權,origin=chatgpt)。三條路最後都收斂到唯一入口 JobService.create_job,在這裡一次做完執行冪等檢查、擁有者檢查與進行中上限檢查,再放進 poster_jobs 佇列,由單一 Worker(python -m app.worker)處理。好處是新增一個 Agent 或 ChatGPT 介面,完全不必重寫核心業務邏輯,維護成本與漏洞風險都跟著降低。

責任交接矩陣:誰檢查,誰動手

責任交接矩陣:BLOB 與檔案不一致、取消或重試工作、匯出圖片三種情境
圖 技術包 p.12 責任交接矩陣:三種情境,各由哪個 Skill 檢查、哪個 Skill 動手。

講義用三個情境把責任切開。BLOB 與檔案不一致時:image-jobs 只負責檢查並報錯,release 才負責真正動手修復。取消或重試工作時:image-jobs 帶 --user,以擁有者權限執行、不寫稽核;admin-console 不帶 --user,以管理者權限執行,強制寫入 job.cancel 稽核。匯出圖片時:image-jobs 只讀資料庫匯出自己的圖、不寫稽核;admin-console 匯出他人原圖,強制補寫 image.download。這和第 03 課「看別人的圖不記、下載別人的圖才記」是同一個邏輯。

情境image-jobsadmin-console/release
BLOB 與檔案不一致images.py verify:只檢查並報錯release 的 backup.py reconcile:真正動手修復
取消/重試工作帶 --user:擁有者權限,不寫稽核admin-console 不帶 --user:管理者權限,強制寫入 job.cancel 稽核
匯出圖片讀 DB 匯出自己的圖,不寫稽核admin-console 匯出他人原圖,強制補寫 image.download

上表是把 p.12 的矩陣照圖重打成文字。

本課重點

  • Admin Console 有四個獨立狀態儀表;上線前先跑 13 項 Preflight,再用 SQLite 線上 API 備份並立刻驗證。
  • 一張海報從建庫、註冊、白名單、選快照、組提示詞、提交、產圖到備份與驗收,每個 Skill 只管自己的一段。
  • 網站、內建 Agent、ChatGPT 三種來源都走 JobService.create_job,檢查只寫一份。
  • 檢查與動手分開;管理者做的事強制寫稽核,擁有者自己的操作不寫。
06 / 07

第 07 課・技術包 p.13–15

安全金字塔與驗收邊界

最後一課是整份技術包的安全收尾:指令依危險程度分四級、哪些部分已經自動驗證過、哪些還需要人工驗收,以及給維護者與 AI Agent 共同遵守的五條規範。

四級安全金字塔

安全金字塔與部署閘門:L0 到 L3 與預設 MOCK_OPENAI
圖 技術包 p.13 安全金字塔與部署閘門(Security Pyramid & Deployment Gates)。

指令按危險程度分四級,越往上越要多一道確認。L0 是唯讀查詢(list、show、check),不需要特殊旗標;L1 是可復原的寫入(register、submit),終端機會顯示「模式=寫入」;L2 是破壞性或不可逆的動作(publish、cancel、revoke),必須加 --yes,否則拒絕;L3 是產品線環境,最高警報,必須加 --confirm-production 而且事先備份。金字塔底下的預設基石是 MOCK_OPENAI=true(離線假網關),不花額度,也絕對隱私遮蔽(密碼雜湊、金鑰不印)。

級別性質例子要加什麼
L0唯讀查詢list、show、check不需特殊旗標
L1可復原寫入register、submit終端機顯示「模式=寫入」
L2破壞性/不可逆publish、cancel、revoke--yes,否則拒絕
L3產品線環境(圖上未舉例)--confirm-production,且事先備份

上表是把 p.13 的金字塔照圖重打成文字。

哪些驗證過,哪些還要人工

通過驗證區與未驗證、人工驗收區
圖 技術包 p.14 左:通過驗證區(Automated & Verified);右:未驗證/人工驗收區(MANUAL Reality Check)。

左邊已經自動驗證的有四項:假網關行為、備份與還原流程、RWD 顯示、系統與腳本互動(Preflight checks)。右邊還需要人工驗收的也有四項:真實的 Agents API(未用真實帳號實測)、真實的 Sandbox/Computer Use(未用真實環境跑過)、真實的 ChatGPT Connector(OAuth 轉址與授權畫面)、真實的高解析度圖像生成(API 耗時、審核錯誤)。講義的系統宣告是:誠實標示邊界,是高品質工程文件的體現;腳本涵蓋業務邏輯,但與真實外部世界的接口仍需要人工驗收。

維護者飛行前檢查

維護者飛行前檢查清單五項
圖 技術包 p.15 維護者飛行前檢查(Maintainer's Checklist),五個打勾項目。

最後一張是給維護者、也是給 AI Agent 共同遵守的五條:資料庫一律用 open_context 取得,不自己寫 SQL 或自己建 engine;所有時間一律用不帶時區的 UTC,不混用本地時間;輸出絕不印出 BLOB、憑證明文或完整的 .env 金鑰;寫入類指令確認要加 --yes(不可逆)或 --confirm-production;結束碼嚴格遵守 0(成功)、1(檢查未過)、2(用法或前置錯誤)。底部的結語是:這不只是一套海報產出系統,更是與 AI Agent 安全協作的標準工程規範(SOP)。

本課重點

  • 指令分 L0 到 L3 四級:唯讀、可復原寫入、不可逆(--yes)、產品線(--confirm-production 加事先備份)。
  • 預設走離線假網關 MOCK_OPENAI=true,不花額度、不印密碼雜湊與金鑰。
  • 講義誠實標出邊界:真實 Agents API、Sandbox、ChatGPT Connector、高解析度生成都還沒實測,需要人工驗收。
  • 五條維護規範:用 open_context 取資料庫、一律 UTC、不印祕密、寫入要確認旗標、結束碼 0/1/2。
07 / 07