# 3.9 Logs Management (ประวัติการแก้ไข / Audit Log)

---

title: 'Functional Requirements: Audit Log Management'
version: 1.8.1
status: updated
owner: Nattanin Peancharoen
last_updated: 2026-03-24
related:

- specs/01-requirements/01-01-objectives.md
- specs/01-requirements/01-03-modules/01-03-00-index.md
- specs/01-requirements/01-06-edge-cases-and-rules.md
- specs/03-Data-and-Storage/03-01-data-dictionary.md
- specs/01-requirements/01-02-business-rules/01-02-01-rbac-matrix.md
- specs/06-Decision-Records/ADR-010-logging-monitoring.md

---

## 3.9.1. วัตถุประสงค์

Audit Log บันทึก **ทุก action สำคัญ** ในระบบ — ทั้ง CRUD เอกสาร, การ Login/Logout, เหตุการณ์ Security — เพื่อ Traceability, Compliance และการ Debug ในระบบ Production

---

## 3.9.2. โครงสร้างข้อมูล (Database Table)

ใช้ตารางเดียว `audit_logs` ออกแบบสำหรับ **High-Volume Append-Only Write**:

| Column | Type | หมายเหตุ |
|---|---|---|
| `audit_id` | BIGINT AUTO_INCREMENT | Primary Key (ร่วมกับ `created_at` เพื่อ Partition) |
| `request_id` | VARCHAR(100) | Trace ID เชื่อมกับ Application Log (Distributed Tracing) |
| `user_id` | INT | ผู้กระทำ (ไม่มี FK — ป้องกัน Partition constraint) |
| `action` | VARCHAR(100) | รหัส action เช่น `rfa.create`, `login.success` |
| `severity` | ENUM | `INFO` / `WARN` / `ERROR` / `CRITICAL` |
| `entity_type` | VARCHAR(50) | Module/ตาราง เช่น `rfa`, `correspondence` |
| `entity_id` | VARCHAR(50) | Primary ID ของ record ที่ได้รับผลกระทบ |
| `details_json` | JSON | ข้อมูล Context เพิ่มเติม |
| `ip_address` | VARCHAR(45) | IP Address ของผู้กระทำ |
| `user_agent` | VARCHAR(255) | Browser/Client ของผู้กระทำ |
| `created_at` | DATETIME | เวลาที่กระทำ |

**Primary Key:** `(audit_id, created_at)` — รวม `created_at` เพื่อรองรับ **Partition Table**
**ไม่มี FK** — ใช้ INDEX แทน เพื่อให้ Partition ทำงานได้ (MariaDB constraint)

---

## 3.9.3. Action Format

รูปแบบ: `<module>.<action>` — เช่น:

| action | ความหมาย |
|---|---|
| `login.success` / `login.failed` | เข้าสู่ระบบ |
| `rfa.create` / `rfa.update` / `rfa.delete` | CRUD RFA |
| `correspondence.create` / `correspondence.submit` | สร้าง / Submit Correspondence |
| `circulation.create` / `circulation.close` / `circulation.force_close` | Circulation |
| `drawing.upload` / `drawing.delete` | อัปโหลด / ลบ Drawing |
| `file.virus_detected` | ClamAV พบ Virus |
| `file.mime_mismatch` | MIME Type ไม่ตรง |
| `user.deactivate` / `user.reactivate` | เปลี่ยนสถานะ User |

---

## 3.9.4. Severity

| severity | ใช้เมื่อ |
|---|---|
| `INFO` | ทุก CRUD ปกติ, Login สำเร็จ |
| `WARN` | Login ล้มเหลว, Re-assign Circulation |
| `ERROR` | ระบบ Error, Failed Transaction |
| `CRITICAL` | File Virus Detected, Force Close Circulation, Security Event |

---

## 3.9.5. Partitioning (Performance)

`audit_logs` ใช้ **RANGE Partition by YEAR(created_at)**:

```
p_old    → ก่อน 2024
p2024    → 2024
p2025    → 2025
...
p2030    → 2030
p_future → หลัง 2030
```

- Query เฉพาะ Partition ที่เกี่ยวข้อง → ลด I/O อย่างมีนัยสำคัญ
- Drop Partition เพื่อ Archive ข้อมูลเก่าได้โดยไม่กระทบ Production

---

## 3.9.6. RBAC

| การกระทำ | Role ที่อนุญาต |
|---|---|
| ดู Audit Log ทั้งหมด | Superadmin, Org Admin (เฉพาะ org ตัวเอง) |
| Export / Report | Superadmin |
| ลบ Audit Log | **ห้ามลบ** — Append-Only เสมอ |

---

## 3.9.7. กรณีที่บันทึก Audit Log บังคับ

| กรณี | severity | ระบุใน Edge Case |
|---|---|---|
| Cancel Correspondence ที่มี Circulation เปิด | `CRITICAL` | EC-CORR-001 |
| Force Close Circulation + reason | `CRITICAL` | EC-CIRC-001, EC-CIRC-002 |
| Re-assign Circulation (Assignee deactivated) | `WARN` | EC-CIRC-001 |
| File Virus Detected (ClamAV) | `CRITICAL` | EC-FILE-001 |
| File MIME Type Mismatch | `WARN` | EC-FILE-002 |
| ทุก Login / Logout | `INFO` / `WARN` | — |
| ทุก CRUD บน Document ทุกประเภท | `INFO` | — |
