Skip to content

19.3 · 12-month platform modernization

ขอบฟ้า เดือน 6–12 — งานระดับสถาปัตยกรรมที่ ROI ของ deep scorecards จัดไว้ท้ายลำดับ เพราะ investment สูง แต่ถ้าไม่ทำ pattern เดิมจะเกิดซ้ำใน service ใหม่

/ Months 6–12 — platform-level work that deep scorecards put late in ROI order: high investment, but without it the same failure modes recur in every new service.

แกนของบทนี้: (1) central secret manager, (2) NestJS consolidation & service boundaries, (3) ลบวัฒนธรรม backdoor / @Public() debug, (4) token & frontend standard, (5) dependency LTS baseline

ไม่ใช่ "rewrite ทั้งแพลตฟอร์มใน Go" — deep docs ไม่สนับสนุน big-bang rewrite; vtrc-api/10 ระบุชัดว่า Sequelize 5→6 / Node 12→20 / Apollo v2→v4 ไม่คุ้มถ้าไม่มี feature บังคับ


หลักการก่อนเริ่มขอบฟ้า 12 เดือน

  1. 19.1 ต้องผ่าน Definition of Done — อย่าเริ่ม secret manager บน credential ที่ยังไม่ rotate
  2. 19.2 ต้องมี transaction / cron ที่เสถียรพอ — อย่าย้าย DB boundary ตอนข้อมูลยัง partial-write
  3. อ่าน 19.4 — modernization ≠ cosmetic rename

Pillar 1 — Central secrets manager

ทำไมต้องมี (หลักฐานซ้ำ)

หลักฐานCitation
13+ repo มี secret ใน git (deep redo)Vol 12.5 secrets cluster
SECRET_KEY แชร์ benefit / recruitment / ai-recruitment / pmspms-api SEC-PMS-02
Fallback secret ในซอร์ส 2way-apiSEC-2WAYAPI-02
ROI ท้ายของหลาย service ชี้ "ย้ายไป secret manager"benefit ROI #5, vtrc-api ROI #10, pms ROI #3 ต่อเนื่อง

หลัง rotate มือใน 90 วัน — ถ้ายัง copy .env ข้าม repo ด้วยมือ จะรั่วรอบใหม่ภายในปี

Target architecture

┌─────────────────────┐
│ Secret Manager      │  Vault / AWS SM / GCP SM
│ (rotatable, audited)│  (องค์กรมี GCP SA pattern อยู่แล้ว — อย่า commit key)
└─────────┬───────────┘
          │ runtime fetch / CSI / init container

┌─────────────────────┐
│ Each service boot   │  fail-fast ถ้าขาด key — ไม่มี fallback string
│ JWT secret ต่อ svc  │  เลิก share ข้าม domain
└─────────────────────┘

งานย่อย (เรียง)

#งานผล
1.1เลือก tooling ที่ ops รองรับจริง (GCP SM น่าจะสมเหตุสมผลกว่าเพิ่ม Vault ถ้ายังไม่มี)ลด tooling sprawl
1.2มาตรฐานชื่อ secret path ต่อ service / envvtrc/{env}/{service}/{key}
1.3Migrate ชุด A (domain Nest) ก่อน — benefit, recruitment, ai-recruitment, pmsปิด shared JWT
1.4Migrate legacy vtrc-api / cu-central-apiแยก JWT_SECRET จาก default culture
1.5Auto-rotation policy + runbook ใน Vol 16rotate ไม่พึ่ง chat
1.6แยก JWT secret ต่อ service — เลิก forge ข้ามแพลตฟอร์มpms-api remediation #5

Anti-goal

  • ห้ามใส่ secret ใหม่ลง Docker image bake (SEC-COMMON-03 pattern)
  • ห้าม commit .env.example ที่มีค่าจริง
  • ห้ามใช้ NEXT_PUBLIC_* สำหรับ secret ที่ต้องเก็บฝั่ง server (2way-api encrypt.util fallback)

Pillar 2 — NestJS consolidation & service boundaries

2.1 สถานะปัจจุบัน (จาก deep docs)

แพลตฟอร์มมี NestJS อยู่แล้วในกลุ่ม 2way / Domain / Meeting แต่ยังมี:

ปัญหาตัวอย่างCitation
Distributed monolith (cross-DB)workflow-api TypeORM ตรงไป schema อื่น; pms-api workforce coupling ×10CORR-WORKFLOW-01; ARCH-PMS-01
Dual schema ไม่ syncbenefit.wdHospitals vs vtrc.WDHospitalsbenefit-api ROI #8
Legacy GraphQL monolith ผสม REST PDFvtrc-apivtrc-api ROI #5
Fork ซ้ำ backofficevtrc-backofficevtrc-backoffice-newdependency + bug เดียวกัน
Placeholder 8 ตัวว่างattendance/auth/career/…workspace structure

2.2 NestJS consolidation — ความหมายในเล่มนี้

Consolidation ในที่นี้ = ทำให้ Nest services มี มาตรฐานเดียวกัน ไม่ใช่รวมทุกอย่างเป็น monorepo เดียวในวันเดียว

มาตรฐานที่ต้องล็อกภายใน 12 เดือน:

มาตรฐานรายละเอียด
Authglobal JwtAuthGuard เป็น default; @Public() ต้องมี ADR + owner
Config@nestjs/config + secret manager; ห้าม fallback string
SQLparameterized เท่านั้น; raw string concat = CI fail
CronScheduleModule + distributed lock; document timezone
Loggingpino / nest-winston กลาง; no-console ใน CI
Health/health + readiness ทุก service
vtrc-commontreat เป็น internal library บน branch prod — ไม่ bake secret

2.3 แยก workload จาก vtrc-api

vtrc-api/10 ROI #5: แยก REST PDF/Excel generation ออกจาก GraphQL server

vtrc-api (GraphQL + auth + domain)

        │ queue / internal HTTP

pdf-worker (Nest or existing worker)
  qpdf via execFile — ไม่มี shell
  scale แยกจาก API pods

คู่กับ ROI #8 — แทนที่ node-schedule ด้วย BullMQ + Redis lock สำหรับ leader election ที่เชื่อถือได้

2.4 ลด cross-DB access

ลำดับปลอดภัย:

  1. Inventory ทุก connection ที่ชี้ schema คนละเจ้าของ (เริ่มจาก workflow / pms workforce / benefit dual)
  2. Freeze — ห้าม PR เพิ่ม connection ใหม่
  3. อ่านผ่าน API ของเจ้าของข้อมูล (ช้ากว่าแต่มี auth/validation จุดเดียว)
  4. เขียนเฉพาะผ่านเจ้าของ — เลิก dual-write

Effort: สัปดาห์–เดือน ต่อ domain (pms-api ROI #9)

2.5 รวม / deprecate frontend forks

คู่การตัดสินใจที่ต้องมีภายในปี
vtrc-backoffice vs vtrc-backoffice-newmerge หรือ deprecate ตัวหนึ่ง — bug isRemember / AntD / react-scripts ซ้ำ
meeting-backoffice vs meeting-backoffice-newยืนยันสถานะย้าย; เลิกฝัง static build ด้วยมือใน vtrc-backoffice
8 placeholder APIsimplement ตาม timeline หรือ archive อย่างเป็นทางการ

2.6 Placeholder repos — decision once

attendance-api, auth-api, career-api, hrservice-api, learning-api, notification-api, payroll-api, performing-api

แต่ละตัวเลือก (ก) timeline implement หรือ (ข) archive — อย่าปล่อยสถานะคลุมเครือให้ทีมใหม่เริ่มซ้ำ


Pillar 3 — Remove backdoors as a culture (ไม่ใช่แค่ลบ 3 จุด)

การลบ i3admin / testnaja / signinbypass ใน 90 วันเป็น incident response

งาน 12 เดือนคือกันไม่ให้เกิดใหม่:

Controlรายละเอียด
ADR: ห้าม hardcode credentials ในซอร์สรวม test user — ใช้ seed + env เฉพาะ UAT
CI rule: fail ถ้าพบ @Public() บน method ที่ชื่อ add/update/delete/import/salaryallowlist ต้องมี comment + ticket
Code review checklist"มี NODE_ENV gate หรือไม่" ไม่พอ — prod path ต้องไม่มี backdoor
Pentest regressioncurl จาก Vol 12.5 exploit examples ทุก release train
Audit logalert เมื่อ empCode === 'adm9999' หรือ path /signinbypass

อ้าง 2way-api remediation: ถ้าต้องการบัญชีทดสอบ — seed + feature flag ปิดใน prod; อย่า comment โค้ด backdoor ไว้


Pillar 4 — Token storage & frontend platform standard

ปัญหาซ้ำ

ทุก frontend/mobile เก็บ token ในที่ JS อ่านได้ — Vol 12.5, vtrc-web SEC-VTRC-WEB-01, vtrc-rc-backoffice SEC-VTRC-RC-05

ADR ที่ต้องมี (ฉบับเดียวทั้งองค์กร)

หัวข้อค่ามาตรฐานที่แนะนำ
Access tokenHttpOnly Secure SameSite cookie
CSRFdouble-submit หรือ synchronizer token คู่ cookie
Refreshrotate + bind device/apiKey
SSO handoffPOST body — ห้าม path segment
XSS defenseCSP + dompurify (ทำไปแล้วใน 90 วันต้องคงไว้)
Reference implหนึ่ง repo เป็นแม่แบบให้ copy

ROI: HttpOnly เป็นข้อใหญ่ใน frontend scorecards (#6 web, #7 rc-bo) — ทำหลัง CSP/dompurify เพราะต้องแตะ backend set-cookie

Bundle / build modernization (รอง)

จาก vtrc-web/07 ROI และ vtrc-rc-backoffice/07:

งานเมื่อไหร่
Code splitting / AntD tree-shake / lazy Stimulsoftหลัง security cookie หรือคู่ขนานทีม frontend
Replace moment.js (ระวัง Buddhist year)ปานกลาง — sync conversion
Webpack 5 + Node 18/20ใหญ่ — อย่าผสมกับ AntD major ใน PR เดียว
AntD v3→v4 บน vtrc-webrewrite ทุก form (getFieldDecorator) — โปรเจกต์แยก

Pillar 5 — Runtime & dependency LTS baseline

Baseline ที่ควรประกาศเหตุผล
Node.js LTS เดียวสำหรับ repo ใหม่ตอนนี้กระจาย 12–20
React / AntD policy สำหรับ frontend ใหม่เลิกเพิ่ม CRA 3.4.3
รอบ upgrade ทุก 6 เดือนตาม Node LTSไม่ใช่ ad-hoc ตอนโดน CVE

งาน EOL ที่เหลือจาก Wave 3 เดิม (LEG-*) จัดเข้าขอบฟ้านี้หลัง security/correctness — ยกเว้น typosquat (LEG-CU-01) ที่ควรจบใน 90 วันแล้ว


Pillar 6 — Service-to-service communication

ปัจจุบันTarget
Hardcoded IP ไม่มี TLS (SEC-2WAYLINE-02)internal DNS + HTTPS/mTLS
Public endpoint + apiKey อ่อน / @Public()gateway + service identity
Dual centralize callers ใน 2wayชัด ownership ทีมต่อ endpoint

อย่าเปิด endpoint ใหม่แบบ "ชั่วคราว public" — นั่นคือที่มาของ SEC-BENEFIT-03 / SEC-PMS-01


แผนรายไตรมาสภายในปี (หลังเดือน 6)

Q3 (เดือน 6–9)
├── Secret manager path + migrate ชุด A
├── JWT secret แยกต่อ service
├── ADR: @Public() / backdoor / token cookie
├── pdf-worker spike จาก vtrc-api
└── Freeze cross-DB connections ใหม่

Q4 (เดือน 9–12)
├── Migrate legacy secrets เข้า SM
├── HttpOnly cookie pilot (rc-backoffice หรือ web)
├── เริ่มแทน cross-DB ด้วย API (1 domain)
├── Backoffice fork decision executed
├── Placeholder archive/implement decision
└── LTS baseline ประกาศ + CI Node version gate

Mapping ROI ท้ายลำดับ → pillar

Deep ROI (ท้าย)Pillar
benefit #5 ย้าย secret manager1
vtrc-api #5 แยก REST PDF / #8 BullMQ / #10 Vault1, 2
pms #9 ลด workforce coupling / #10 tests2
2way #7–10 LINE HTTPS, encrypt, dead modules, Node unify2, 5, 6
vtrc-web #6 HttpOnly / #8 Webpack 54, 5
vtrc-rc-backoffice #7–10 cookie, CRA, MUI consolidate4, 5
Vol 12.5 ROI #6 frontend hardening4

Success metrics (12 เดือน)

Metricเป้า
Secret ใน git (secret scan)0 บน default/canonical branches
Shared JWT ข้าม domain0
@Public() บน write/PII โดยไม่มี ADR0
Hardcoded backdoor password0
Cross-DB connections ใหม่หลัง freeze0
Services ที่ boot จาก secret manager≥ ชุด A + vtrc-api
Frontend ที่ใช้ HttpOnly สำหรับ session≥ 1 pilot ใน prod

ไป 19.4 · What NOT to rewrite