稽核事件查詢 Runbook — 誰做了什麼、何時做的

給原廠/管理者:如何從 DB 查出「誰、做了什麼專案進度行為、何時」的時間線。 本期(FR-033)只提供 SQL 查詢;尚無查詢 API / UI。


0. 先搞懂:兩套 log 看哪一個

想查的東西 看哪張表 為什麼
業務事件時間線(誰推進流程、誰完成任務、誰改問卷狀態) public.system_logs 語意明確,一筆一事件,含 event_code
某人某時打了哪支 HTTP API(含 request body) public.api_logs 全自動記錄每個 request,但要靠 path/body 解讀
登入 / 登出 / 使用者管理 public.system_logs 既有 audit event

多數稽核需求看 system_logs 以下 SQL 以它為主。


1. system_logs 欄位對照

欄位 意義 對應問題
act_time 事件發生時間 何時
user_uid 操作者 UUID
user_name 操作者暱稱(nickname) (人看得懂)
event_code 事件碼(見 §2) 做了哪類事
message [AUDIT:...] key=value 結構化訊息 做了什麼(含 project_id / task_uid 等)
level INFO / WARNING / ERROR
method / func_name / line_no / path 程式位置(debug 用)

保留期:180 天(按 act_time 月分區)。api_logs 為 90 天。


2. 事件碼(event_code)對照

event_code 意義 來源
4624 / 4625 登入失敗 / 成功 既有
4634 登出 既有
6050 流程推進請求 既有 STAGE_ADVANCE
6051 流程推進成功 既有
6052 流程退回成功 既有
6053 推進中止(warning) 既有
6054 推進被擋 既有
6060 任務完成 FR-033
6061 任務指派 / 批次指派 FR-033
6062 任務改派 FR-033
6063 任務退回指派 FR-033
6070 問卷狀態變更(送審/通過/退回,看 from_status→to_status FR-033

問卷狀態碼:0=未填寫, 1=編輯中, 2=待審核, 3=補充說明, 9=完成。 例:from_status=1 to_status=2 = 送審;from_status=2 to_status=3 = 審核退回補件;to_status=9 = 審核通過完成。


3. 連線資訊

環境 Host Port DB 帳號
DEV 192.168.50.188 25432 guidant_ai_dev cmmgr(密碼查 .env DB_SECRET
STG 192.168.50.188 25432 guidant_ai_stg 同上
POC 192.168.50.189 25432 guidant_ai_poc 同上
# 連線範例(密碼請查 .env,勿寫進任何檔案)
PGPASSWORD='<查 .env DB_SECRET>' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev

4. 查詢範例(可直接複製)

4.1 某段時間內,誰做了哪些專案進度行為(總時間線)

SELECT act_time, user_name, event_code, message
FROM public.system_logs
WHERE event_code IN ('6051','6052','6060','6061','6062','6063','6070')
  AND act_time >= '2026-06-01 00:00:00'
  AND act_time <  '2026-06-05 00:00:00'
ORDER BY act_time;   -- 時間正序 = 時間線

4.2 查特定使用者做了什麼(依暱稱)

SELECT act_time, event_code, message
FROM public.system_logs
WHERE user_name = '王小明'
  AND act_time >= now() - interval '30 days'
ORDER BY act_time DESC;

4.3 查某個專案的完整進度時間線

-- 任務指派/完成的 message 帶 project_id;流程推進/問卷狀態用 task_uid 串
SELECT act_time, user_name, event_code, message
FROM public.system_logs
WHERE message LIKE '%project_id=88%'
  AND event_code IN ('6060','6061','6062','6063')
ORDER BY act_time;

4.4 查某張任務(task_uid)誰指派、誰改派、誰退回、誰完成

SELECT act_time, user_name, event_code, message
FROM public.system_logs
WHERE message LIKE '%task_uid=ef34%'   -- 換成實際 task_uid
ORDER BY act_time;

4.5 查某份問卷的狀態變更歷程(送審→退回→通過)

SELECT act_time, user_name, message
FROM public.system_logs
WHERE event_code = '6070'
  AND message LIKE '%task_survey_uid=gh56%'   -- 換成實際 task_survey_uid
ORDER BY act_time;

4.6 查所有「退回」動作(流程退回 + 問卷退回補件)

SELECT act_time, user_name, event_code, message
FROM public.system_logs
WHERE event_code = '6052'                              -- 流程退回
   OR (event_code = '6070' AND message LIKE '%to_status=3%')  -- 問卷審核退回補件
ORDER BY act_time DESC;

4.7 用 HTTP log 反查(補充手段,當 system_logs 不夠時)

-- 知道誰在何時打了某支 API(90 天內)
SELECT act_time, user_name, method, url, duration
FROM public.api_logs
WHERE url LIKE '%/jobs/batch-complete%'
  AND act_time >= now() - interval '7 days'
ORDER BY act_time DESC;

5. 已知限制(誠實告知)

  • 無 tenant 欄位system_logs 不含 tenant_id,無法直接按租戶過濾;需用 user_name / message 內的 project_id 間接區分。
  • Socket.IO 協同編輯不記:問卷逐字協作(on_update)刻意不埋點(量太大);只記狀態轉換。
  • 本期無查詢 API / UI:只能走 SQL。若客戶要 UI 時間線,需另開 feature 做 system_logs 查詢 route。
  • 既有未補的行為:本 FR 補的是「專案進度」核心行為;其他模組(如資產盤點 CRUD)若日後要稽核,照 common/util/audit_log.py + 新增 EventCode 同樣方式埋點即可。

6. 如何擴充(給未來 dev)

要替新行為加稽核:

  1. common/enum/event_code.py 加一個 EventCode(依現有序號往後)
  2. service 層該行為發生處呼叫 audit(logger, "<EVENT_NAME>", EventCode.XXX, key=value, ...)
  3. logger 用 logging.getLogger(__name__)(須是 app/api/infra/domain/common 子 logger 才會寫進 DB)
  4. 寫測試:.__wrapped__ 繞過 @transaction + caplog 斷言(參考 test/test_audit_event_instrumentation.py
  5. 本 runbook §2 事件碼對照表補一列