# FR-033 稽核事件埋點 — 收尾 SUMMARY

| 項目 | 內容 |
|------|------|
| 日期 | 2026-06-04 |
| Branch | main（此 repo 直接在 main 工作，與近期 commit 一致）|
| 範圍 | BE only（service 層埋點 + common helper + 文件 + 測試）|
| 觸發 | 「確認所有 API 都有記 log（誰 / 做什麼 / 時間）」盤點 → 補專案進度行為稽核埋點 + 查詢文件 |

## 一、做了什麼 / 行為差異

起點是盤點全站行為 log。發現兩件事，分兩個主題收尾：

### 主題 A — request log middleware 兩個 bug（fix）
`common/middleware/app_mw.py`（HTTP 層 `api_logs` 全自動記錄）：
1. `teardown_request` 組好錯誤訊息 DTO 卻漏呼叫 `update_api_log` → 例外訊息沒進 DB。補上 + 包 try/except。
2. `before_request` 寫 log 無保護 → DB 失敗會讓業務 API 噴 500。包 try/except，失敗只記 error、不設 trace_id。

**行為差異**：例外路徑現在會留訊息；log 寫入失敗不再波及業務 API。

### 主題 B — 專案進度稽核事件埋點（feat，FR-033）
語意事件層 `system_logs` 原本只記流程推進 / 退回、登入、使用者管理。補上 5 個 event_code：

| code | 行為 | 埋點 |
|---|---|---|
| 6060 JOB_COMPLETED | 任務完成 | job_batch_complete_service |
| 6061 TASK_ASSIGNED | 指派 / 批次 | task_assignee_service（add / batch_add）|
| 6062 TASK_REASSIGNED | 改派 | task_assignee_service（update）|
| 6063 TASK_UNASSIGNED | 退回指派 | task_assignee_service（delete）|
| 6070 TASK_SURVEY_STATUS_CHANGED | 問卷狀態變更 | question_answer_service ×2 + task_survey_service ×2 |

統一走 `common/util/audit_log.py` 的 `audit()`，產出 `[AUDIT:<event>] key=value`；「誰 / 時間」由 DBLogHandler 自動補，不改 signature。

**行為差異**：完成任務 / 指派 / 改派 / 退回指派 / 問卷送審通過退回，都會在 `system_logs` 留一筆可稽核事件。

## 二、commits（皆已 push 到 origin/main）

| commit | 主題 |
|--------|------|
| `fd8aa9ed` | fix: app_mw.py teardown + before_request |
| `82227d66` | feat(FR-033): audit event logging + docs + tests |
| `08f904af` | docs(changelog): 回填 commit hash |
| `0424daea` | docs(conversation-history): 歸檔今日 7 session |

## 三、規範文件清單

- ✅ changelog ×2：`2026-06-04-fix-api-log-middleware-teardown-and-before-request.md`、`2026-06-04-feat-fr033-audit-event-logging.md`
- ✅ design.md + audit-log-query-runbook.md（FR-033 資料夾）
- ✅ FR 登記表（docs/features/README.md 加 FR-033）
- ✅ 本 SUMMARY
- ✅ Notion 任務頁「各種行為日誌補齊」5 區段補齊
- 無 issue（兩 bug root cause 顯而易見）/ 無 analysis（取捨已在 design.md §4）

## 四、測試

- 單元 14 綠（helper 3 + 埋點 11，含負向案例）
- 回歸 31 綠（task_assignee / stage_advance）
- ✅ 線上驗證通過（2026-06-07）：真實使用者操作已寫入 `system_logs` —
  `[AUDIT:TASK_ASSIGNED] project_id=246 count=4 user_count=2 control_count=1`（6061，Billows Admin）
  + `[AUDIT:TASK_SURVEY_STATUS_CHANGED]` ×4（6070，Bob / Billows Admin）。
  誰（user_name）/ 做什麼（event_code+context）/ 何時（act_time）三要素皆正確落地。
  6060/6062/6063 期間無人觸發故 0 筆，pattern 已由 6061+6070 證實 end-to-end 正常。

## 五、已知 follow-up / 不在本期 scope

- system_logs 查詢 API / UI 時間線（本期只做 SQL runbook）
- Socket.IO 逐字協同編輯埋點（刻意不做）
- 問卷狀態歷史表等結構性補強
- `system_logs` 無 tenant_id 欄位，跨租戶過濾需間接靠 user / project_id
- **middleware 噪音（線上驗證時發現）**：`app_mw.py` 的 `logger.info("API Request...")` /
  `Request Headers` / `Request Body` 走 `middleware` logger（掛了 db handler），每個 request
  寫 3 筆 `event_code='-'` 進 `system_logs`（30 分鐘 ~8000 筆）。HTTP 明細本該只進 `api_logs` /
  檔案，不該塞 `system_logs`。稽核查詢靠 `event_code` 過濾不受影響，但長期應把這 3 行改掉 / 不寫 DB。
  （既有行為，非 FR-033 引入；待 user 決定是否另開 follow-up）

## 六、部署 handover

- BE 無 hot reload，**需重啟**生效
- 無 DB migration（沿用 `public.system_logs`，180 天月分區）
