Skip to content

11.10 · Scorecard + ปัญหา API surface

บทสุดท้ายของ Volume 11 — สรุปคะแนนรวมของ API surface ระบบ VTRC พร้อมระบุปัญหาเร่งด่วนและแนวทางการปรับปรุง


Scorecard — รวม 3 services

ให้คะแนนแต่ละด้านของ API surface ใน 3 services โดยใช้เกณฑ์: 5 = production-grade, 3 = ใช้งานได้แต่มีข้อจำกัด, 1 = เสี่ยง

ด้านvtrc-apicu-central-apicentralize-apiหมายเหตุ
Documentation1.51.02.5มีแค่ centralize Swagger และยังไม่สมบูรณ์
Auth consistency3.52.01.0vtrc-api ดีสุด แต่ cu-central-api public เยอะ centralize-api ไม่มี auth
Error model3.53.02.0มี code catalog แต่ไม่สม่ำเสมอ
Validation3.02.54.0centralize-api ใช้ class-validator (ดีสุด)
Versioning1.01.02.0ไม่มี v1/v2, centralize มี global prefix /api
Rate limiting1.01.01.0ไม่มีเลย
Observability2.02.02.0มี log แต่ไม่มี metrics/tracing
Testability1.01.01.5ไม่มี test ใน service ใด
Security posture2.52.01.5apiKey ฝัง source, centralize ไม่มี auth
Performance3.02.52.5ไม่มี cache, DataLoader หรือ batching

คะแนนรวม

Serviceคะแนนเฉลี่ยระดับ
vtrc-api2.4 / 5ใช้งานได้ แต่มีหนี้เทคนิคสะสม
cu-central-api1.9 / 5เสี่ยงด้าน security (public operations เยอะ)
centralize-api1.9 / 5เสี่ยงด้าน security (ไม่มี auth)
ระบบรวม2.1 / 5ทำงานได้ แต่ต้องปรับปรุงด่วนหลายจุด

ปัญหาเร่งด่วน — 10 อันดับแรก

เรียงตามความรุนแรง (severity × probability × impact)

1. 🔴 centralize-api ไม่มี auth จริง (@Public() ทุก route)

ที่ตั้ง: centralize-api/src/modules/employee/employee.controller.ts:38-120 (ทุก method)

ปัญหา: ทุก endpoint ใช้งานได้โดยไม่ต้อง JWT — ใครเข้าถึง intranet ก็ยิงได้

ผลกระทบ: ข้อมูล HR รั่ว — พนักงานทุกคน (เงินเดือน, ตำแหน่ง, หน่วยงาน)

แก้ไข: ลบ @Public() ออกจาก method ที่ sensitive + เปิดใช้ JWT guard จริง

2. 🔴 cu-central-api HRMI domain public ทั้งหมด (26 ops)

ที่ตั้ง: cu-central-api/main-api/src/typeDefs/hrmi.js (ทั้งไฟล์ไม่มี @auth)

ปัญหา: createLeaveDocument, fetchMedicalExpenses, ฯลฯ — ใครมี apiKey ก็ยิงได้

ผลกระทบ: สร้าง/ลบเอกสารลาของพนักงานคนอื่นได้

แก้ไข: เพิ่ม @auth ในทุก mutation + ตรวจ ownership ใน resolver

3. 🔴 apiKey ฝังใน source code

ที่ตั้ง:

  • vtrc-api/api/src/config.js:42-148 (6 keys × 2 env)
  • cu-central-api/main-api/src/lib/auth/auth.controller.js:257-271 (2 keys)

ปัญหา: secret อยู่ใน git — ทุกคนที่ clone repo ได้ก็ได้ key

ผลกระทบ: apiKey รั่ว → ผู้โจมตีปลอมตัวเป็นแอป

แก้ไข: ย้ายไป env หรือ secret manager (AWS Secrets Manager, Vault)

4. 🔴 vtrc-api ใช้ 404 แทน 401 บน REST

ที่ตั้ง: vtrc-api/api/src/routes.js (หลายจุด เช่น 525, 580, 677, 729)

ปัญหา: auth fail → 404 ทำให้คิดว่าไฟล์ไม่มี จริง ๆ token หมดอายุ

ผลกระทบ: debug ยาก, frontend จัดการ error ผิด

แก้ไข: เปลี่ยนเป็น 401 + JSON error body

5. 🟠 /webdeployment endpoint ไม่มี auth

ที่ตั้ง: vtrc-api/api/src/routes.js:975

ปัญหา: trigger deploy script โดยไม่ต้อง auth

ผลกระทบ: ผู้โจมตีสามารถ trigger deploy ได้ (RCE-level)

แก้ไข: เพิ่ม HMAC signature check หรือ IP whitelist

6. 🟠 static file serving เปิดหมด

ที่ตั้ง: vtrc-api/api/src/routes.js:986-988

ปัญหา: app.use('/', express.static(PWD + '/storage')) — ทุกไฟล์ใน storage เข้าถึงได้โดยไม่ต้อง auth

ผลกระทบ: ไฟล์ sensitive (เช่น payslip ที่อัปโหลด) รั่ว

แก้ไข: เพิ่ม auth middleware หรือใช้ presigned URL เท่านั้น

7. 🟠 ไม่มี rate limiting

ที่ตั้ง: ทั้ง 3 services

ปัญหา: ไม่มี express-rate-limit หรือ custom throttle

ผลกระทบ: DDoS ได้ง่าย โดยเฉพาะ endpoint PDF/export ที่ใช้ CPU หนัก

แก้ไข: ติดตั้ง rate limit middleware (เช่น 100 req/min ต่อ IP)

8. 🟠 typo ติดใน schema สาธารณะ

ที่ตั้ง:

  • ResposeStatus (ควรเป็น ResponseStatus) — vtrc-api
  • INTENAL_SERVER_ERROR (ควรเป็น INTERNAL) — cu-central-api
  • Subscribtion (ควรเป็น Subscription) — cu-central-api
  • fetchAuthSessionMoblie (ควรเป็น Mobile) — vtrc-api

ปัญหา: typo ติดใน schema ที่ frontend ใช้อยู่ → แก้ไม่ได้โดยไม่ break client

ผลกระทบ: ดูไม่เป็นมืออาชีพ, debug สับสน

แก้ไข: coordinate กับ frontend + เปลี่ยนใน major version

9. 🟡 cu-central-api /auth/signinbypass เปิดอยู่

ที่ตั้ง: cu-central-api/main-api/src/lib/auth/auth.js:127-149

ปัญหา: endpoint ที่ login ไม่ต้องใช้ password

ผลกระทบ: ถ้าเปิดใน production — เป็น backdoor

แก้ไข: ตรวจ env ว่าถูก disable ใน prod หรือยัง

10. 🟡 PDF deletePDF 5 วินาที

ที่ตั้ง: vtrc-api/api/src/routes.js:73-82

ปัญหา: หลัง generate PDF แล้ว 5 วินาที deletePDF ลบไฟล์

ผลกระทบ: ถ้า download ช้ากว่า 5 วิ → ไฟล์หาย → 404

แก้ไข: ใช้ streaming หรือเพิ่ม timeout เป็น 5 นาที


ปัญหาที่พบบ่อยตอนพัฒนา

1. ไม่รู้ว่าใช้ GraphQL หรือ REST

  • ใช้ GraphQL สำหรับ query/mutation ทั่วไป
  • ใช้ REST สำหรับ binary (PDF, file, Excel)
  • frontend ส่วนใหญ่ใช้ทั้งคู่ในหน้าเดียวกัน

2. SourceDB ต้องระบุทุกครั้ง

  • ใน cu-central-api SourceDB มาจาก profileKey
  • ถ้าลืม → query อาจ return ข้อมูลผิดคน

3. JWT 2 ตัว

  • frontend ใช้ JWT vtrc-api เท่านั้น
  • แต่ debug ฝั่ง vtrc-api ต้องรู้ว่ามี JWT cu-central-api ซ่อนอยู่ใน Session

4. Forward retry ทำให้ latency สูง

  • ถ้า JWT cu-central-api หมดอายุ → refresh + retry
  • เพิ่ม 200-500 ms ต่อ request

5. Error code ไม่สม่ำเสมอ

  • vtrc-api: TOKEN_EXPIRED
  • cu-central-api: ACCESS_TOKEN_INVALID
  • centralize-api: 401 (HTTP)
  • client ต้องจัดการทั้งหมด

แนวทางการปรับปรุงระยะยาว

ระยะสั้น (1-3 เดือน)

  1. ย้าย apiKey ออกจาก source → env / secret manager
  2. เพิ่ม rate limiting ทุก service
  3. เปลี่ยน REST 404 → 401 ใน vtrc-api
  4. ลบ /webdeployment หรือเพิ่ม auth
  5. ตรวจ /auth/signinbypass ใน prod

ระยะกลาง (3-6 เดือน)

  1. เพิ่ม @auth ใน HRMI ของ cu-central-api
  2. เปิด JWT guard จริง ใน centralize-api (ลบ @Public() บาง route)
  3. เพิ่ม DataLoader ใน resolver ที่มี N+1
  4. migrate memoryStorage → diskStorage ใน multer
  5. เพิ่ม OpenTelemetry เพื่อ trace forward chain

ระยะยาว (6-12 เดือน)

  1. API versioning/api/v1/... /api/v2/...
  2. GraphQL schema registry — ทำให้ breaking change ตรวจได้
  3. migrate Apollo → Apollo Server 4 (ปัจจุบันใช้ v2)
  4. consolidate cu-central-api + centralize-api — มี 2 service ที่ทำงานคล้ายกัน
  5. move file storage → S3/GCS — ลด disk dependency

Best practices สำหรับทีมใหม่

ตอนเขียน GraphQL operation ใหม่

  1. ใช้ @auth(accessRole: [...]) เสมอ (ยกเว้น field ที่ตั้งใจ public)
  2. ใช้ custom scalar (Date, JSON) แทน string
  3. ระบุ return type ให้ชัดเจน — หลีกเลี่ยง JSON เมื่อเป็นไปได้
  4. ใช้ input type สำหรับ mutation ที่มี argument เยอะ

ตอนเขียน REST endpoint ใหม่

  1. ตัดสินใจ auth ให้ชัดเจน (apiKey / JWT / signed URL / public)
  2. ใช้ HTTP status ที่ถูกต้อง (200/400/401/404/500)
  3. มี response envelope ที่สม่ำเสมอ ({ data, error })
  4. เพิ่ม rate limit

ตอนเขียน forward (vtrc-api → cu-central-api)

  1. ใช้ GraphqlCDWithToken เสมอ (ไม่ใช่ fetch ตรง ๆ)
  2. จับ error ที่ cu-central-api ส่งกลับ + map ให้เป็น vtrc-api error code
  3. log ทุก forward call (เพื่อ debug)
  4. ระวัง SourceDB — ส่ง profileKey เสมอ

ตอน debug

  1. ดู บท 10.2 ก่อน — ตรวจ header
  2. ดู บท 10.7 — เข้าใจ error code
  3. ดู บท 10.9 — ถ้าเป็น forward chain
  4. ดู log ฝั่ง server — error ที่ frontend เห็นอาจถูก mask ใน prod

สรุป Volume 11

Volume นี้ครอบคลุม API surface ของระบบ VTRC ทั้งหมด — 3 services, 400 endpoints/operations, 3 ภาษา (JS, JS, TS), 2 frameworks (Apollo, NestJS)

จุดแข็ง

  • Service layering ชัดเจน — frontend → vtrc-api → cu-central-api
  • GraphQL ใช้แล้วดี — frontend มี type safety
  • Signed URL สำหรับ PDF — ป้องกัน enumeration
  • centralize-api มี Swagger — เริ่มต้น documentation
  • class-validator ใน centralize-api — validation ดี

จุดอ่อน

  • Auth coverage ไม่สม่ำเสมอ — public operations เยอะ
  • apiKey ฝัง source — secret management ไม่ดี
  • ไม่มี rate limit — DDoS ได้ง่าย
  • ไม่มี test — ทุก service
  • typo ติดใน schema — ดูไม่เป็นมืออาชีพ

สิ่งที่ต้องทำต่อ

  • ปรับปรุง security — ดู Volume 10
  • เพิ่ม business logic docs — ดู Volume 12
  • ปรับปรุง infrastructure — ดู Volume 13

ไฟล์อ้างอิงหลัก

ไฟล์หน้าที่
vtrc-api/api/src/index.jsApollo + Express bootstrap
vtrc-api/api/src/routes.jsREST 30 endpoints
vtrc-api/api/src/typeDefs/*.jsGraphQL schema (44 files)
vtrc-api/api/src/resolvers/*.jsGraphQL resolvers (42 files)
vtrc-api/api/src/centralize/controllers/graphql.jsForward engine
vtrc-api/api/src/centralize/graphql/queries.js68 forward query templates
vtrc-api/api/src/centralize/graphql/mutations.js17 forward mutation templates
vtrc-api/api/src/lib/responErrors.jsError factory
cu-central-api/main-api/src/index.jscu-central Apollo + Express
cu-central-api/main-api/src/typeDefs/*.jscu-central schema (32 files)
cu-central-api/main-api/src/lib/auth/auth.jsREST auth endpoints
cu-central-api/main-api/src/lib/responseAndLog.jsError factory
centralize-api/src/main.tsNestJS bootstrap
centralize-api/src/modules/employee/employee.controller.ts14 endpoints
centralize-api/libs/exception/http-exception.filter.tsError filter
centralize-api/docs/document.config.tsSwagger config

Volume 11 จบลงตรงนี้

Volume ถัดไป: Volume 12 · Business Logic — เจาะลึก business rule ของแต่ละ domain (leave, welfare, fund, payroll)