給下一棒 runner 的冷接文件。 本文件自包含,看完即可開工,不需回頭翻對話。
上一棒:
2026-07-25-security-arc-final-session-handoff.md(同目錄,資安 arc 第二棒收官)
角色定位:任務執行 runner。 user 指派 Notion case 編號 → 我照 notion-case-work skill 流程做掉 → 回填 Notion 標「修正待驗證」+ 白話補充。
不是 arc 主導、不是分析 session。user 說「執行 CM-xxx」我才動,做完停下等下一個指令。
本棒處理 6 條 case(CM-886~889 / 893 / 新開 894)+ 1 條 user 臨時指派的 UI 一致性修正。
接手後不要自動開始做任何事。 等 user 指派 case 編號。
若 user 直接說「繼續」而沒給編號 → 回問要處理哪一條,不要自己從 Notion 挑。
| Case | 範圍 | 狀態 | commit |
|---|---|---|---|
| CM-886 | FE | 修正待驗證 | c8aa7bc 480090d c634f32 9c59c8b |
| CM-887 | FE | 修正待驗證 | 7b2cd96 |
| CM-888 | BE | 修正待驗證 | ecffff39 |
| CM-889 | BE+FE | 修正待驗證 | f972d92d / a6a895b |
| CM-893 | BE | 修正待驗證 | 456f1a1d + 文件 747bd35c |
| CM-894 | — | Not started(新開,未動工) | — |
| (無 case) | FE | 已 commit | 40e8d4c |
Notion 六條都已回填白話補充。CM-894 是本棒開的新 case、沒做,內容已寫到可直接動工的程度。
settleEnvelope helper,消 S3403/S4822Noto Sans CJK TC40e8d4c:/project/task-manage 狀態篩選 CSS 對齊全站慣例(user 臨時指派,無 case)這三項是本棒實際查證後推翻或補強了 case 原本的假設,下一棒若碰到相關區域要知道:
delete_gitlab_feedback_attachment 收 file_uids 卻立刻用「該 issue 全部附件」覆寫 → 刪一個附件會全刪 GitLab 端。
根因不是隨手寫錯:GitLab 附件 uid 是 note body 裡 /uploads/<hex>/ 的雜湊,local 附件 uid 是 DB uuid,兩者不同 id 空間,拿 local uid 去比對交集恆空、什麼都刪不掉。推測原作者因此改成全刪繞過。
修法:改用檔名比對定位(同名檔案依出現順序 1:1 配對),對不到就回 False 不再退化成全刪。caller 配合改為「先查檔名再刪 local」——順序不可對調,local mapping 刪掉後就查不到檔名了。
case 假設是「內網抓不到只剩等待成本」。實查發現:部署環境(Debian + fonts-noto-cjk)根本沒有 Noto Sans TC 這個家族名——那是 Google Fonts 的名稱,容器內 fc-match 'Noto Sans TC' 掉到 DejaVu Sans(無中文字符)。
中文不會變豆腐字(WeasyPrint 有字符級 fallback),但實測會撿到 Noto Sans CJK JP,也就是用日文漢字字形排繁中報告。故第一順位改指定 Noto Sans CJK TC。
已確認 DEV 主機字型 OK(user 實跑 fc-match 回 NotoSansCJK-Regular.ttc: "Noto Sans CJK TC")。
nosemgrep: 必須在 finding 行的行尾、或緊鄰的前一行。寫成「nosemgrep 獨立一行 + 中文說明換行」會把 nosemgrep 推離錨點,BE 剩 13 條、FE 剩 1 條沒消掉。
正確格式:說明放更前一行,# nosemgrep: <rule> 放行尾。多行語句(logger.warning( / make_response()錨在起始行。
BE ~/Projects/Billows/Audit-Manager/compliance-manager-be main 已同步
FE ~/Projects/Billows/Audit-Manager/compliance-manager-fe main 已同步
BE 有若干 untracked(docs/交付文件/、security-audit-report-2026-07-17.html 等)——本 session 開始前就存在,不是本棒產物,不要順手清。
BE git log 裡這些不是本棒做的,是平行 session 的產物:
| commit | 時間 | 內容 |
|---|---|---|
9de55a8e |
12:23 | semgrep avoid-sqlalchemy-text ERROR 歸零 |
1ac436a5 |
12:41 | SonarQube hotspots 逐條審查 |
d245cb72 |
12:46 | SonarQube Quality Gate new-code 策略 |
e52ea26b |
12:51 | weasyprint 升 69.0(CM-892 CVE) |
e81c8c05 |
13:09 | 摘要報告 img src 限縮 data: URI(CM-892) |
時間戳與本棒的 ecffff39(12:18) / f972d92d(12:58) / 456f1a1d(13:10) 交錯。
對下一棒的影響:
api/project_summary_report/ 這個目錄兩棒都動過(本棒動 template 字型、平行棒動 route 的 bleach 白名單)→ 動之前先 git log 看最新狀態本棒沒有啟動也沒有重啟 BE。session 中觀察到 PID 33978 在跑(port 8000,啟動時間 13:05),是 user 先前自己起的,跑的是舊 code。
CLAUDE.md 記載 2026-07-22 起 BE 重啟由 Claude 負責,但因該 process 非我所起、user 可能正在使用,我問過後 user 未回覆是否重啟 → 維持未重啟。
這是本棒唯一「改了會動資料、但只驗語法」的項目。
_is_gitlab_enable() 為 false),這條路徑根本不會執行複測步驟已寫在 Notion CM-888 頁。下一棒若 user 回報「刪附件有問題」,優先看這裡。
CM-888 改的是 service 層,CM-893 改的是 template(理論上隨請求讀取、不需重啟,但既然同輪有 service 改動,一起重啟最保險)。
目前跑的 BE 是舊 code。
CM-893 拔掉 Google Fonts 外連後,「主機有中文字型」從隱藏的保險變成明確前提。
auditmanager-dev-01:✅ 已確認(Noto Sans CJK TC 正常解析)上線前各跑一次:
fc-match 'Noto Sans CJK TC' # 要回 NotoSansCJK,不是 DejaVu若某台沒裝,這個 commit 在那台會讓中文從 PDF 整段消失(實測:完全無中文字型時中文不是豆腐字,是不見)。
auditmanager-dev-01 跑任何 apt-get install 都會報 libpython3.11-stdlib 版本不一致。與本棒工作無關(字型套件本身已是最新版)。
⚠️ 不要跑 apt --fix-broken install——會動系統 python,該機正在跑 BE。要處理需另案評估。
已寫進 docs/claude/host-dependencies.md。
docs/claude/host-dependencies.md(新檔,commit 747bd35c)主機層依賴(部署前提)——記錄「poetry install 裝不到、但缺了功能會壞」的 OS 層套件:
fonts-noto-cjk(摘要報告 PDF)CLAUDE.md 的 Environment Variables 段已加 pointer + LIBREOFFICE_CMD 選用變數。
下一棒若動到 PDF / 匯出相關,先讀這份。 CM-894 完成後需回填多語系字型段。
CM-894(本棒新開,Not started):PDF 匯出多語系字型缺漏。
case 內已含完整診斷指令(可直接重跑)與逐語系實測對照表。
git add 逐檔列名,禁用 -A / -am小弟(Claude 做的),來源 雷門,專案 CM/private/tmp,不寫入 docs/security-reports/ 日期資料夾npm run build:DEV(指令是 build:DEV 不是 build)git diff 逐行比對,確認每個刪除行都以「原內容+註記」形式回來(CM-889 用此法確認零邏輯異動)見同目錄 2026-07-25-runner-session-prompt.md,或直接用本文件開頭那段。