15.9 Debt heat-map
บทนี้จัด debt ทั้งหมดในมุม severity × effort เพื่อช่วยตัดสินใจจัดลำดับ
วิธีอ่าน heat-map
แกน X = effort ที่ต้องใช้ (จากน้อยไปมาก) แกน Y = severity (จากต่ำไปสูง)
| Quadrant | ความหมาย | กลยุทธ์ |
|---|---|---|
| มุมบนซ้าย | severity สูง, effort ต่ำ | ทำทันที (quick win ที่สำคัญ) |
| มุมบนขวา | severity สูง, effort สูง | วางแผนระยะยาว (strategic) |
| มุมล่างซ้าย | severity ต่ำ, effort ต่ำ | ทำตอนมีเวลา (quick win) |
| มุมล่างขวา | severity ต่ำ, effort สูง | เลื่อนไปทีหลัง (defer) |
Heat-map (ASCII)
Severity
▲
│
│ ┌─ SEC-4 JWT default ┌─ LEG-1 Node 12 EOL
│ │ SEC-2 playground prod │ LEG-2 esm shim
│ │ SEC-5 centralize CORS * │ LEG-3 Apollo v2 EOL
│ │ PERF-7 phpMyAdmin │ LEG-4 React 16 + Apollo v2
│ │ SEC-11 GCP SA key │ PERF-1 execSync blocking
│ │ CORR-6 syncModelToTable │ CORR-1 cross-schema write
│ │ SEC-1 qpdf injection │ CORR-4 RBAC bug
│ │ │ LEG-19 in-process cron
C │ │ │
r │ │ │
i │ │ ▼
t │ │ Strategic
i │ │
c │ │
a │ │ ┌─ PERF-6 god controller 3,179 LOC
l │ │ │ LEG-21 queries monolith
│ │ │ LEG-22 route duplication
│ │ │ LEG-17 TS safety off
│ │ │ LEG-10 html-pdf + node-qpdf
│ │ │ LEG-5 AntD split
│ │ │ LEG-6 react-scripts
│ │ │ LEG-7 Webpack 4
│ ▼ │
│ │
│ Stop-the-bleed │
│ (do now) │
│ │
│ ┌─ SEC-10 rate limit │
│ │ SEC-9 typosquat pkg │
│ │ SEC-8 PII in URL │
│ │ SEC-7 axois typo │
│ │ SEC-6 trustServerCert │
│ │ PERF-2 no-cache │ ┌─ LEG-26 duplicate UI libs
│ │ PERF-3 session LIKE │ │ LEG-23 resolver 3,716 LOC
│ │ PERF-4 N+1 RBAC │ │ LEG-25 typo ENUMs
│ │ PERF-5 sync approval │ │ LEG-30 i18n in error
│ │ CORR-2 txn swallow │ │ LEG-20 axios 16+ instances
│ │ CORR-3 responError │ │ LEG-14 _bk files 131
│ │ CORR-5 log query │ ▼
│ │ CORR-7 column dupe │
│ │ CORR-8 PDF race │ Defer / batch
│ │ CORR-9 httpRequest │
│ │ LEG-15 no lockfile │
│ │ LEG-16 dual lockfile │
│ │ LEG-18 no engines │
│ │ LEG-13 s, stream │
│ │ LEG-12 redis v3 │
│ │ LEG-11 driver dupe │
│ │ LEG-9 jwt v8 │
│ │ LEG-8 ldapjs │
│ │ LEG-27 xlsx CVE │
│ │ LEG-28 sha512crypt │
│ │ LEG-29 firebase │
│ │ PERF-8 network host │
│ │ │
│ └─ Quick wins │
│ │
│ Med severity │
│ ▼ │
└─────────────────────────────────────────────────────► Effort
1 day 1 week 1 month 3+ monthsหมายเหตุ: ตำแหน่งเป็นการประมาณ เพื่อช่วยตัดสินใจ ไม่ใช่การวัดที่แม่นยำ
ตาราง severity × effort
ตารางเดียวกันในรูปแบบตาราง เรียงตาม priority:
Priority 1 — ทำทันที (severity สูง, effort ต่ำ)
รายการเหล่านี้เป็น quick win ที่ลดความเสี่ยงวิกฤตได้ภายใน 1-2 สัปดาห์
| ID | รายการ | Effort |
|---|---|---|
| SEC-4 | JWT_SECRET default 'secret' | 30 นาที |
| SEC-2 | playground + introspection prod | 30 นาที |
| SEC-5 | centralize CORS * | 30 นาที |
| CORR-6 | syncModelToTable in prod | 1 ชั่วโมง |
| PERF-7 | phpMyAdmin เปิดสาธารณะ | 1 ชั่วโมง |
| LEG-13 | s, stream, findit ไม่ใช้ | 30 นาที |
| LEG-15 | centralize ไม่มี lockfile | 30 นาที |
| LEG-16 | vtrc-web สอง lockfile | 30 นาที |
| LEG-18 | ไม่มี engines | 30 นาที |
| CORR-7 | column dupe | 30 นาที |
| CORR-9 | httpRequest.js | 30 นาที |
| CORR-5 | centralize log query | 30 นาที |
| SEC-7 | axois typo | 30 นาที |
| SEC-1 | qpdf injection | 1 วัน |
| SEC-3 | device keys in repo | 2-3 วัน |
| SEC-11 | GCP SA key | 1-2 วัน |
| LEG-9 | jwt v8 → v9 | 1 วัน |
| SEC-9 | typosquat packages | 1 วัน |
| LEG-27 | xlsx CVE | 1 วัน |
Priority 2 — ทำใน Wave 1 (severity สูง, effort ปานกลาง)
| ID | รายการ | Effort |
|---|---|---|
| SEC-10 | rate limit | 2-3 วัน |
| SEC-8 | PII in URL | 2-3 วัน |
| SEC-6 | trustServerCert | 1-2 วัน |
| PERF-2 | no-cache policy | 1-2 วัน |
| PERF-3 | session LIKE JSON | 1-2 วัน |
| PERF-4 | N+1 RBAC | 2-3 วัน |
| PERF-5 | sync approval | 2-3 วัน |
| CORR-2 | txn swallow | 1-2 วัน |
| CORR-4 | RBAC inconsistency | 1-2 สัปดาห์ |
| CORR-3 | responError pattern | 1 สัปดาห์ |
| LEG-8 | ldapjs → ldapts | 2-3 วัน |
| LEG-12 | redis v3 → v4 | 2-3 วัน |
| LEG-28 | sha512crypt | 1 วัน |
| LEG-29 | firebase + googleapis | 2-3 วัน |
| PERF-8 | network_mode host | 1 วัน |
Priority 3 — ทำใน Wave 2 (strategic — severity สูง, effort สูง)
รายการเหล่านี้ต้องวางแผนเป็นโครงการ
| ID | รายการ | Effort |
|---|---|---|
| LEG-1 | Node 12 → 20 | รวมกับ LEG-2 |
| LEG-2 | esm shim → native ESM | 2-3 สัปดาห์ |
| LEG-3 | Apollo Server v2 → v4 | 1-2 สัปดาห์ |
| LEG-4 | React 16 → 18 + Apollo v3 | 2-4 สัปดาห์ต่อ frontend |
| LEG-19 | in-process cron → distributed | 1-2 สัปดาห์ |
| PERF-1 | execSync → worker queue | 3-5 วัน |
| CORR-1 | cross-schema write | architectural |
| PERF-6 | god controller split | 1-2 สัปดาห์ |
| LEG-10 | html-pdf → Playwright | 1 สัปดาห์ |
Priority 4 — Defer (severity ต่ำ, effort สูง)
| ID | รายการ | Effort |
|---|---|---|
| LEG-5 | AntD split | 1 สัปดาห์ |
| LEG-6 | react-scripts → Vite | 1-2 สัปดาห์ |
| LEG-7 | Webpack 4 → 5 | 1 สัปดาห์ |
| LEG-17 | TS strict mode | 1-2 สัปดาห์ |
| LEG-21 | queries monolith | 1-2 สัปดาห์ |
| LEG-22 | route duplication | 1 สัปดาห์ |
| LEG-23 | resolver 3,716 LOC | 1 สัปดาห์ |
| LEG-20 | axios 16+ | 1 สัปดาห์ |
Priority 5 — Quick wins (severity ต่ำ, effort ต่ำ)
| ID | รายการ | Effort |
|---|---|---|
| LEG-14 | _bk files 131 | 1-2 วัน |
| LEG-25 | typo ENUMs | (map ตอน rewrite) |
| LEG-26 | duplicate UI libs audit | 1 สัปดาห์ |
| LEG-30 | i18n in error | 2-3 วัน |
| LEG-11 | driver dupe | 1 วัน |
| CORR-8 | PDF race | 1 วัน |
การกระจายตาม repo
ตารางนี้แสดงว่า debt แต่ละรายการอยู่ใน repo ใด — ช่วยวางแผนการกระจายงานในทีม:
| Repo | Critical | High | Med | รวม |
|---|---|---|---|---|
| vtrc-api | 8 | 13 | 3 | 24 |
| cu-central-api | 2 | 7 | 2 | 11 |
| centralize-api | 2 | 2 | 1 | 5 |
| vtrc-web | 0 | 4 | 4 | 8 |
| vtrc-rc-backoffice | 0 | 3 | 5 | 8 |
| ข้าม repo / global | 1 | 2 | 0 | 3 |
สังเกต: vtrc-api มี debt มากที่สุด เพราะเป็น service หลักที่ใหญ่ที่สุด ความพยายามในการลด debt ควรกระจายไปยังทุก repo ไม่ใช่ vtrc-api อย่างเดียว
บทสรุปของ heat-map
- มี Critical debt ที่ effort ต่ำอยู่ 8-10 รายการ — ทำ Wave 0 ให้จบภายใน 1-2 สัปดาห์เพื่อลดความเสี่ยงทันที
- Critical ที่ effort สูง (Node 12, RBAC, cross-schema) ต้องวางแผนเป็น Wave 2
- vtrc-api มี debt มากที่สุด — ควรมีนักพัฒนา 1-2 คนที่ focus การลด debt ใน repo นี้
- frontend (vtrc-web, backoffice) มี debt ระดับ Med ที่กระจาย — ทำได้ช้าลงโดยไม่กระทบวิกฤต
บทถัดไปจะนำ heat-map ไปจัดลำดับเป็น Wave 0/1/2/3 ที่เป็น action plan