Day 20 的跨情境總覽已經能重驗 5 次實驗與 15 組結果,但一份可交付作品不能只靠我記得腳本先後順序。如果盤點、建置與驗證各自有一套入口,使用者就可能只生報告、沒有重驗來源,或是看到 HTML 能開啟,卻不知道它是否對應當前證據。
Day 25,我把這些步驟收進 xss-evidence-workbench/workbench.py。它是單一指令列入口,底下只有 inventory、build 與 verify 三個子指令。這不會讓證據變多,卻能讓「查什麼、生什麼、如何知道沒有被改」成為一份可重複的合約。
我先在專案根目錄執行唯讀盤點:
.venv/bin/python xss-evidence-workbench/workbench.py inventory --output /tmp/xss-entry-inventory.json
inventory 只解析 release.json 列出的保存 HTML。本次共處理 15 份文件,從 Day 16 與 Day 18 找到 6 份表單,保留 method、action、具名欄位與提交按鈕覆寫屬性。它也會列出行內事件屬性,以及 location.hash、URLSearchParams、innerHTML、textContent 這類候選訊號。這些資料只是後續查證的線索;解析器沒有開啟頁面、執行 JavaScript 或送出表單,所以不會把「出現危險 API 名稱」直接寫成漏洞結論。
接著,我用同一個入口建置發布物:
.venv/bin/python xss-evidence-workbench/workbench.py build
build 會重跑 Day 20 的來源檢查,確認情境、案例、原始回應雜湊、表單來源與雙重執行訊號一致;然後依 release.json 釘住的 5 個 AI 報告批次,用現行驗證器重驗 15 組 report、evidence 與 schema,再連回 5 份作者核對紀錄。任一數量或關係不符,建置就停下來。
這個入口也保留了測試與重建所需的可調整邊界。--project 可以指向具有同樣目錄結構的專案副本,--config 可以指定發布設定,build 與 verify 則都能用 --output 選擇發布目錄。這讓我可以在臨時目錄進行負向測試,不必改動正式 dist/。不過,參數可調不代表範圍可以任意擴張:設定必須符合 schema 版本、產品欄位、預期數量、5 個指定報告來源與不重複的盤點路徑,否則還沒進入建置就會被拒絕。
錯誤也是 CLI 合約的一部分。當路徑超出專案、JSON 無法讀取、原始證據不一致或發布檔雜湊不符時,程式會在標準錯誤輸出列出原因,並回傳狀態 1。使用者不需要從一個只建出一半的 dashboard 反推哪個關卡失敗。
建置成功後,dist/ 裡會有 4 份檔案:
| 檔案 | 我用它回答的問題 |
|---|---|
evidence-bundle.json |
完整的機器可讀證據、情境、案例、盤點與關卡是什麼? |
report.md |
我如何快速閱讀與比較本次結果? |
index.html |
沒有伺服器時,如何用靜態頁面瀏覽同一批證據? |
manifest.json |
這三份內容檔是否屬於同一次發布? |
manifest.json 不假裝自己能證明自己;它記錄另外 3 份輸出的 SHA-256,並用產品版本加上 evidence bundle 雜湊前 16 碼形成 release ID。
每份輸出會先寫到同目錄的臨時檔,再取代最終路徑。這不能讓 4 份檔案在任何意外下都一次交換完成,但至少不會讓單一目標檔在寫入一半時就被當成完整結果。
verify 不只是重算一個雜湊最後,我執行:
.venv/bin/python xss-evidence-workbench/workbench.py verify
verify 會先要求 manifest 檔案清單正好是 evidence-bundle.json、report.md 與 index.html,再核對現有檔案的 SHA-256。這一層可以立刻擋下被替換或缺少的發布檔。接著,程式會從當前來源重建 bundle、Markdown 與 HTML,再進行逐位元比對;因此,即使有人同時重算了發布檔的雜湊,只要內容不是由現行來源重建,還是會停下來。最後才核對 release ID。
這個順序也讓錯誤比較容易解讀。如果 report.md 只被改了一個字,第一層就會回報該檔案的 SHA-256 不符;如果三份檔案和 manifest 被一起替換,第二層仍會用當前來源重建內容。我不需要用肉眼在數百行 JSON 中尋找差異,也不會因為 HTML 可以正常開啟就跳過機器可讀內容的比對。
Day 25 的結果是:我終於不必再用一長串腳本順序來解釋作品。一個 CLI 負責盤點、建置與驗證,4 份輸出各有明確責任。明天,我要從功能而不是檔名出發,宣布這個作品到底完成了什麼。
那就…
明天見!