3.3.9 · Scorecard, ownership, what's next
บทสุดท้ายสรุปสถานะของ centralize-api ในรูปแบบ scorecard, ownership mapping, เปรียบเทียบกับ services อื่นใน platform, และแนะนำขั้นตอนต่อ
Scorecard
| มิติ | Score | หลักฐาน |
|---|---|---|
| Functional correctness | 6/10 | endpoints ทำงานได้ แต่ขาด test (บท 3.3.1 — dead spec/e2e) |
| Security | 2/10 | 4 Critical + 7 High (บท 3.3.8) |
| Code quality | 4/10 | CTE copy-paste (3.3.4), profanity (3.3.4), dead code (3.3.1) |
| Maintainability | 4/10 | TypeScript strict ปิด (3.3.1), dependency outdated (3.3.1) |
| Documentation | 5/10 | Swagger setup มี แต่ response type ไม่ annotated (3.3.7) |
| Observability | 3/10 | logger ไม่ rotate (3.3.7), ไม่มี metric/trace |
| Production-readiness | 3/10 | ไม่มี helmet, compression, health endpoint (3.3.7) |
| Test coverage | 1/10 | spec/e2e fail/dead (3.3.1) |
| Total | 3.5/10 |
อ่านเพิ่มเติม — scorecard นี้ base บท evidence ในบท 3.3.1–3.3.8 score ต่ำเพราะ auth bypass + credential leak ที่ยังไม่แก้
Ownership — ใครรับผิดชอบอะไร
centralize-api ไม่มี CODEOWNERS file ใน repo → สรุปจาก package.json author + รูปแบบ code
| ส่วน | รับผิดชอบ (推测) | หลักฐาน |
|---|---|---|
| API surface (17 endpoints) | ทีม VTRC API | DTO naming convention เหมือน vtrc-api |
| HRMI integration (raw SQL) | ทีม VTRC API + ทีม HRMI (CU/RC) | raw SQL อ้าง HRMI tables, CASE WHEN mapping SourceDB → code |
| Auth (JWT, guard) | ทีม VTRC API | copy pattern จาก starter template |
| Deployment (Docker, CI/CD) | DevOps | Dockerfile + npm scripts |
| HRMI schema (tables, views) | ทีม CU/RC (ไม่ใช่ทีม VTRC) | HRMI = HR Management Information ของจุฬา/สภากาชาด |
การสื่อสารข้ามทีม
| สถานการณ์ | ทีมที่ต้องประสาน |
|---|---|
| เพิ่ม endpoint ใหม่ | ทีม VTRC API (caller: vtrc-api) |
| เปลี่ยน HRMI table structure | ทีม CU/RC (HRMI owner) |
| เพิ่ม index บน HRMI table | ทีม CU/RC |
| เปลี่ยน MSSQL server | DevOps + ทีม VTRC API |
| แก้ security debt (บท 3.3.8) | ทีม VTRC API + DevOps |
เปรียบเทียบกับ services อื่นใน platform
| Aspect | centralize-api | cu-central-api | vtrc-api | 2way-api |
|---|---|---|---|---|
| Stack | NestJS + TypeORM + MSSQL | Node + Sequelize + MSSQL/LDAP | Node + Apollo GraphQL + Sequelize + MariaDB/MSSQL | NestJS + Mongoose + MongoDB |
| Lines of code | ~2,500 | ~5,000+ | ~30,000+ | ~10,000+ |
| Endpoints | 17 REST | ~50 REST | GraphQL (hundreds of resolvers) | ~80 REST |
| Auth | JWT guard bypass (@Public) | apiKey header | @auth(accessRole) directive + apiKey | NestJS JWT guard (works) |
| Test coverage | 1/10 | 1/10 | 1/10 | 3/10 |
| Security debt | 22 issues | TBD | ~30+ issues (Vol 3.1) | ~10 issues (Vol 5) |
| Documentation depth (v2) | บท 3.3.1–3.3.9 (this) | บท 3.2 (planned) | บท 3.1 (planned) | บท 5 (planned) |
จุดสำคัญ
- centralize-api มีขนาดเล็กที่สุดในกลุ่ม legacy core → ใช้เวลา remediate น้อยที่สุด
- security posture แย่ที่สุดในกลุ่ม เพราะ auth bypass ทั้งระบบ
- แต่ risk ต่ำกว่า vtrc-api เพราะเป็น backend-to-backend เท่านั้น (ไม่ internet-facing โดยตรง)
Migration / modernization path
ระยะสั้น (1–3 เดือน)
| ขั้น | Action | Impact |
|---|---|---|
| 1 | Fix Phase 1 (บท 3.3.8 §"Phase 1 — minimal fix") | ลด critical risk |
| 2 | ลบ dead code (UserEntity, EmployeeResponseDto, spec/e2e ที่พัง) | ลด confusion |
| 3 | เปิด TypeScript strict + แก้ type error | ลด runtime bug |
| 4 | เพิ่ม health endpoint + helmet + compression | production-ready |
ระยะกลาง (3–6 เดือน)
| ขั้น | Action | Impact |
|---|---|---|
| 5 | Implement real JWT validation (lookup user in DB, check revoked) | close auth bypass |
| 6 | เปลี่ยน logging: ['query'] → logging: ['error'] + redact PII | prevent PII leak |
| 7 | อัปเกรด NestJS 8 → 10, moment → date-fns | security patch + ลด bundle size |
| 8 | เพิ่ม unit test สำหรับ service layer (target 50% coverage) | confidence ในการแก้ bug |
ระยะยาว (6–12 เดือน)
| ขั้น | Action | Impact |
|---|---|---|
| 9 | Refactor CTE copy-paste → helper function หรือ HRMI view | DRY + ลด bug surface |
| 10 | สร้าง entity สำหรับทุก table ที่ใช้บ่อย | type safety + ลด raw SQL |
| 11 | เพิ่ม OpenTelemetry tracing | observability |
| 12 | พิจารณา merge เข้า vtrc-api ถ้า caller มีอันเดียว | ลด service count |
Open questions — สิ่งที่ยังไม่ชัดเจน
| คำถาม | เหตุผลที่ยังไม่กระจ่าง |
|---|---|
| Caller จริงของ centralize-api คือใคร? | ไม่มี doc ระบุชัด vtrc-api มี env END_POINT_CENTRALIZE แต่ไม่มี evidence ใน code ว่าใช้จริง |
auth_user table อยู่ที่ไหน? | UserEntity อ้างถึง แต่ table ไม่มีใน HRMI — dead code? |
centralize/ folder ใน vtrc-api เกี่ยวข้องกับ centralize-api ไหม? | ชื่อคล้ายกัน แต่ข้อมงใน vtrc-api ชี้ไปยัง cu-central-api ไม่ใช่ NestJS centralize-api |
ทำไม source code มี fuckQuery? | อาจเป็น frustration ตอน debug → ควรถาม original author |
ทำไม secret key คือ 127.0.0.1? | placeholder ที่ไม่ได้ replace? |
| HRMI tables มี index บน SourceDB ไหม? | ไม่มี doc — ต้อง inspect HRMI database โดยตรง |
| TypeORM ทำไมถึง register entity ทั้ง center + NBC เข้า center connection? | glob pattern *.entity match ทั้งคู่ (บท 3.3.2, 3.3.6) |
V1 corrections — แก้ไขจาก V1 documentation
บทนี้รวม drift ที่พบระหว่าง V1 documentation (docs-v1-archive/volume-05-centralize-api/) กับ source code ปัจจุบัน (centralize-api/)
| V1 claim | Actual (current code) | Chapter |
|---|---|---|
V1: addServer() ×4, setDescription(''), addTag() ×4 | จริง: addServer() ×2 (env-driven PORT), setDescription('Centralize API'), ไม่มี addTag | 3.3.7 |
| V1: Dockerfile 3-stage mixed yarn/npm | จริง: 2-stage exclusively yarn, COPY .env ./ explicit | 3.3.2 |
V1: hrTimeTemp.dto.ts — ShiftTimeType/ResponseGetShiftTimeWithWork class, timeIn/timeOut Date | จริง: เป็น interface, timeIn/timeOut string | 3.3.3 |
V1: SourceDB non-nullable on EmployeeLevel/TechnicalPosition | จริง: nullable ทุก entity | 3.3.6 |
V1: HttpExceptionFilter ~46 LOC verbose, logs path/method/timestamp | จริง: 26 LOC คืน { statusCode, message }, log เฉพาะ message | 3.3.7 |
V1: hrpayslip service [...body.empCode] spread operator | จริง: spread operator ยังอยู่ แต่ line number เปลี่ยน | 3.3.4 |
V1: ไม่ได้พูดถึง RootObject interface ใน app.controller.ts | จริง: มี RootObject interface unused | 3.3.3 |
สรุปประเด็นสำคัญของบททั้งหมด (3.3.1–3.3.9)
ขนาดของระบบ
- ~2,500 LOC TypeScript
- 17 REST endpoints (1 ปัจจุบันใช้ + 16 employee/HR)
- 6 live entity + 1 dead (
UserEntity) - 2 MSSQL databases (center + NBC) → cross-database query ผ่าน raw SQL
- 1 caller confirmed (vtrc-api ผ่าน
END_POINT_CENTRALIZEenv) — caller อื่นยังไม่ยืนยัน
Architecture
- NestJS module pattern → 1 module per business domain
- Service layer ใช้ raw SQL เป็นหลัก (TypeORM active record เป็นรอง)
- Multi-tenant sharding ผ่าน
SourceDBcolumn - No GraphQL, no message queue → simple REST API
Security posture
- Critical:
.envcommit, Dockerfile copy.env, JWT secret =127.0.0.1,@Public()บนทุก route - High: CORS wildcard, JWT validation ผิด, PII log, hardcoded IP, profanity, TLS verify off
- Medium: ไม่มี rate limit, helmet, health endpoint, entity coverage ไม่ครบ, TypeScript strict ปิด, deps outdated
- Low: dead code, CTE copy-paste,
console.log
Trust model
centralize-api ออกแบบเป็น internal-only → trust network layer → ปัญหา security ทั้งหมด "less critical" ในสภาพแวดล้อมที่ trust แต่จะ "catastrophic" ถ้า expose ออก internet โดยไม่แก้
Action items ที่จำเป็น
- Phase 1 — ลบ
.env, ลบCOPY .env, ลบ@Public()บน PII endpoint (ภายใน 1 สัปดาห์) - Phase 2 — close HIGH issues (ภายใน 1 เดือน)
- Phase 3 — modernize (TypeScript strict, deps upgrade, tests) (backlog)
Dependency graph — inbound + outbound
เพื่อให้เห็นภาพ risk ของการเปลี่ยนแปลง centralize-api นี่คือ dependency ที่เกี่ยวข้อง
Inbound (อะไรเรียก centralize-api)
| Caller | Protocol | Endpoint | Evidence |
|---|---|---|---|
vtrc-api | HTTP REST | END_POINT_CENTRALIZE env | vtrc-api/api/.env.example:36-37 (Vol 3.1) |
| อื่น ๆ | ไม่ยืนยัน | — | ไม่มี doc ระบุ |
หมายเหตุ — ชื่อ env END_POINT_CENTRALIZE ใน vtrc-api อาจชี้ไปยัง cu-central-api (NestJS ตัวเดิม) หรือ centralize-api (ตัวใหม่) ไม่ชัดเจน — ต้อง verify ใน Vol 3.1
Outbound (centralize-api เรียกอะไร)
| Callee | Protocol | Purpose | Evidence |
|---|---|---|---|
MSSQL dbHRMI_Center | TDS (port 1433) | HR data ของ RC Central | centralize-api/src/app.module.ts:25-40 |
MSSQL dbHRMI_Center_NBC | TDS (port 1433) | HR data ของ RC NBC | centralize-api/src/app.module.ts:44-58 |
| (ไม่มี HTTP outbound) | — | — | ไม่มี HTTP client ใน codebase |
→ centralize-api เป็น "leaf service" — ไม่เรียก service อื่น จึงไม่มี risk จาก downstream failure (นอกจาก MSSQL เอง)
Failure modes ที่คาดการณ์ได้
| Failure | Symptom | Severity |
|---|---|---|
MSSQL dbHRMI_Center down | ทุก endpoint ที่ query center → 500 | High |
MSSQL dbHRMI_Center_NBC down | endpoint ที่ query NBC → 500, แต่บาง endpoint cross-join → 500 ด้วย | High |
| Network latency center ↔ NBC | endpoint ที่ cross-database join ช้า | Medium |
| Disk full จาก log file | ทุก endpoint ค่อย ๆ ช้า → eventually fail | Medium |
| JWT secret mismatch กับ caller | แต่เพราะ @Public() bypass → ไม่กระทบ | None (ปัจจุบัน) |
Cost estimate — remediation effort
ประมาณการ effort สำหรับแต่ละ phase (สมมุติ 1 dev + รู้จัก NestJS + MSSQL)
| Phase | Items | Effort (dev-days) | Risk if skip |
|---|---|---|---|
| Phase 1 — minimal fix | CRIT-01, 02, 03, 04 | 3–5 | credential leak, auth bypass ongoing |
| Phase 2 — high priority | HIGH-01 → 07 | 7–10 | PII leak, MITM, etc. |
| Phase 3 — medium | MED-01 → 06 | 10–15 | regressions, slow incident response |
| Phase 4 — low + cleanup | LOW-01 → 05 | 3–5 | maintainability drift |
| Total | 23–35 dev-days | (~1.5–2 months for 1 dev) |
หมายเหตุ — ตัวเลขนี้ไม่รวม test writing ซึ่งเป็น prerequisite ของบาง fix (เช่น การลบ @Public() ต้องมี integration test ก่อนเพื่อยืนยันว่า JWT flow จริง ๆ ทำงาน)
Recommendation — ควร decommission ไหม?
| ตัวเลือก | ข้อดี | ข้อเสีย |
|---|---|---|
| Fix in place (Phase 1–3) | เก็บ separation of concerns, ใช้ stack ที่ทีมรู้จัก | ใช้เวลา 1.5–2 เดือน |
| Merge เข้า vtrc-api | ลด service count, ใช้ auth + logger ของ vtrc-api | vtrc-api ใหญ่แล้ว, migration risk |
| Merge เข้า cu-central-api | stack คล้ายกัน (Node + MSSQL) | cu-central-api มี debt ของตัวเอง (Vol 3.2) |
| Decommission + ไม่แทนที่ | ถ้า caller จริง ๆ มี vtrc-api ตัวเดียว → vtrc-api อาจไป query HRMI ตรง ๆ ได้ | ต้อง verify caller ก่อน |
→ แนะนำ — ทำ Phase 1 + 2 ก่อน (fix security debt) แล้วค่อยตัดสินใจเรื่อง merge/decommission หลังมี test coverage + ownership ชัดเจน
Definition of done — เกณฑ์ว่า centralize-api "แก้แล้ว"
เกณฑ์ที่จะใช้ตัดสินใจว่าบท 3.3 นี้ outdated แล้ว (คือ dev แก้ code จน score ดีขึ้น)
| เกณฑ์ | Target | ปัจจุบัน |
|---|---|---|
| Critical issues | 0 | 4 |
| High issues | 0 | 7 |
| Test coverage | ≥50% | ~0% |
| TypeScript strict | เปิด | ปิด |
| Health endpoint | มี | ไม่มี |
.env in git | ไม่มี | มี |
| Auth bypass | ปิด | เปิด |
→ เมื่อทุกเกณฑ์ผ่าน → รีวิวใหม่ + ปรับ scorecard
อ้างอิง
- V1 documentation:
docs-v1-archive/volume-05-centralize-api/(read fully before writing — 10 files, ~2,744 lines) - Source code:
centralize-api/(read + verified against V1) - Style guide:
docs/_style/style-guide.md - Workspace structure:
.cursor/rules/workspace-structure.mdc - Related volumes — Vol 3.1 (vtrc-api), Vol 3.2 (cu-central-api), Vol 3.4 (legacy core data flow)
จบบทที่ 3.3
บทต่อไป — 3.4 cu-central-api (Vol 3.4) และ 3.5 vtrc-api (Vol 3.5) — ใช้รูปแบบ depth เดียวกับบท 3.3 นี้