Skip to content

19.4 · What NOT to rewrite (public contracts & intentional typos)

บทนี้คือ เบรก ของ modernization — รายการที่ deep scorecards ระบุว่าเป็น public contract (ENUM, env name, file path, GraphQL operation, magic number) ซึ่งดู "ผิด" แต่มี consumer ใน frontend / DB / deployment พึ่งอยู่

/ This chapter is the brake on modernization — items deep scorecards list as public contracts. They look wrong but have live consumers; renaming them casually breaks production.

กฎเหล็ก จาก vtrc-api/10 Public contract: เจอแล้วไม่แน่ใจ — ถามทีม HR/i3 ก่อนเสมอ ห้ามเดาใน PR security/correctness


ทำไมต้องมีบทนี้

ทีมที่เข้ามาใหม่มักเปิด PR แนว:

  • แก้ typo PEDDING_CANCLEPENDING_CANCEL
  • rename from/form/
  • unify wdHospitals / WDHospitals
  • ลบ @Public() บน dropdown เพราะ "ไม่ควร public"

ทุกอันนี้อาจถูกต้องในระยะยาว แต่ ห้ามทำใน PR เดียวกับ rotate secret / ลบ backdoor / แก้ SQLi — blast radius คนละแบบ และ rollback ยาก

ขอบฟ้าที่ถูกสำหรับ rename คือโปรเจกต์แยก มี migration + dual-read + sync frontend + ops env พร้อมกัน


A · vtrc-api — สัญญาที่ต้องคงแม้ดูผิด

ที่มา: vtrc-api/10 § Public contract

รายการที่ตั้งเหตุผลที่ต้องคงถ้าจะแก้จริงต้อง
PEDDING_CANCLEmodels/core/leave/leave.js:59ENUM sync ลง DB หลายตารางmigration ครบทุกตาราง + ทุก client
DRAFconfig.js statusHrmimapping จาก cu-central-apisync ทั้งสองฝั่ง
CONINCLE_USERNAMEconfig.js, deployment .envชื่อ env ที่ pipeline ใช้coordinate ops เปลี่ยนทุก env
Moblie filenamelib/controllers/auth/authSessionMoblie.jsimport path หลายไฟล์rename + update ทุก import ใน PR ใหญ่แยก
KEY_PLASMA, KEY_HRconfig.js:153-154UUID org จริงใน prod DBsync ทุกที่ที่ hardcode
corssindex.js:76typo key ของ CORS configแก้พร้อม SEC-VTRC-API-06 ทั้งชุด — dual-read key ชั่วคราวถ้าต้อง
signInByPass (centralize controllers)centralize callersบาง flow อาจตั้งใจเช็คทุก caller ก่อนลบ — คนละตัวกับ /auth/signinbypass ของ cu-central ที่ต้องลบใน 90 วัน
tr ใน redis.controller.js:16redis wrapperlandmine ถ้า revive cacheแก้ก่อนเปิด Redis อีกครั้งเท่านั้น
responError / getResapeMessageกระจายทั้ง repoimport หลายร้อยจุดcodemod แยก ไม่ปน feature
APP_NO = 1,2,3,5 (ไม่มี 4)config.jscron leader electionเปลี่ยนลำดับไม่ได้โดยไม่ redesign election
clouselib/clouse.jsfile name ใน importแก้ logic ได้; rename ไฟล์ต้องแยก

สิ่งที่ต้องแก้ใน 90 วัน vs สิ่งที่ต้องคงชื่อ

แก้พฤติกรรม (ทำ)คงชื่อ/สัญญา (อย่า rename)
ลบ default JWT_SECRET='secret'ชื่อ env JWT_SECRET เอง
ปิด command injection qpdfpath ของ routes ที่มี client เรียก
ใส่ auth ที่ /file/:id/downloadชื่อ param :id
แก้ CORS ให้ allowlist ทำงานพิจารณา dual-support corss+cors ชั่วคราว

B · vtrc-web — public contract

ที่มา: vtrc-web/07 § Public contract

รายการที่ตั้งเหตุผล
from/ folder typocomponents/user/from/import ทุกที่ — QUAL-VTRC-WEB-01 ระบุห้ามแก้ import ลวก ๆ
AntD v3 getFieldDecoratorกระจาย formsไม่มีใน v4 — upgrade = rewrite ทุก form เป็นโปรเจกต์แยก
moment.js th_TH + Buddhist yearกระจายเปลี่ยน library ต้อง sync conversion ปี พ.ศ.
GraphQL operation names PascalCasequeries.js, mutations.jsbackend resolver matching
Mutations.login (ไม่มี suffix)mutations.jsต่างจาก Mutations.loginBackoffice ของ rc-backoffice — ห้าม unify ชื่อ
apiKeyNews()utils/apiKey.jsคืน device key ของ WEB APP_TYPE

modernization ที่ทำได้โดยไม่แตะสัญญาเหล่านี้

จาก vtrc-web/07 ROI:

  1. dompurify — ทำได้ทันที
  2. CSP header — ทำได้ทันที
  3. Code splitting / AntD tree-shake — ไม่ต้อง rename folder
  4. HttpOnly cookie — เปลี่ยนที่เก็บ token ไม่ต้องเปลี่ยนชื่อ mutation

C · vtrc-rc-backoffice — public contract

ที่มา: vtrc-rc-backoffice/07 § Public contract

รายการที่ตั้งเหตุผล
TheamCss route + folderApp/index.js:23, pages/TheamCss/typo ที่ import ทั่ว; QUAL-VTRC-RC-01 ห้ามแก้ลวก; ใช้เป็น CSS preview tool
Mutations.loginBackofficegraphql/mutations.jssuffix BO — แยก flow จาก user-side
Queries.refreshTokenBOgraphql/queries.jsrefresh แยก
getOrganization() จาก sessionStorageutils/auth.jsreset sessionStorage = login fail
apiKeyNews()WEB_ADMINutils/apiKey.jsbackend map apiKey → APP_TYPE
AntD v4 Form.useForm() ปน v3 getFieldDecoratorกระจายmigration ทีละ form — ห้าม mix ใน form เดียว
2way-meeting-backoffice embedded SSOpathLogin patternเปลี่ยน handoff ต้องคุย 2way

ทำได้ทันทีโดยไม่ rename

vtrc-rc-backoffice/07 ROI: ลบ .env + rotate, POST body SSO, dompurify, CSP, lazy Stimulsoft — ไม่ต้องแตะ TheamCss


D · benefit-api — public contract

ที่มา: benefit-api/06 § Public contract

รายการที่ตั้งเหตุผล
docType magic numbers 1–5payments / disaster / disbursementfrontend ส่งเลขเหล่านี้
Triple DB names db, dbHRMI, vtrcDBconfiguration.tsinjection token — rename กระทบทุก service
SECRET_KEY env var nameconfiguration.ts:5pipeline ใช้ชื่อนี้ — เปลี่ยนค่าได้; เปลี่ยนชื่อต้อง coordinate
wdHospitals vs WDHospitals casingentity vs raw SQLคนละ schema — ห้าม unify โดยไม่ migrate
SFTP paths upload/fmis/bgdoc/ ฯลฯexportpaymentreport.service.tsFMIS server คาด path เหล่านี้
@Public() บน dropdowndropdown.controller.tsfrontend อาจเรียกตอนยังไม่ login — ลบต้อง verify

แยกให้ชัดจากสิ่งที่ต้องลบ @Public()

เก็บไว้ก่อน (verify กับ frontend)ลบใน 90 วัน
dropdown @Public()wdHospitals add/update/detail (SEC-BENEFIT-03)
batchJob / upload public (SEC-BENEFIT-04/05)

E · pms-api — สิ่งที่อย่าทำพัง / อย่า "cleanup" ผิดจุด

ที่มา: pms-api/06 § สิ่งที่ทำได้ดีแล้ว และ Low findings

รายการคำแนะนำ
*History audit tablesห้ามลบเพื่อลดตาราง
Parameterized sp_get_employeeSalary_*ห้ามแทนด้วย raw string SQL "ให้อ่านง่าย"
ThrottlerGuardห้ามถอดตอนเปิด auth
ValidationPipe forbidNonWhitelistedห้ามผ่อนเพื่อให้ frontend ส่ง field เกินโดยไม่ตั้งใจ
QUAL-PMS-06 typo periodExtesnd filenameLow — rename เป็นโปรเจกต์แยกถ้าจำเป็น
CONF-PMS-01 ชื่อ env JWT_EXPIRE_IN / REFRESH_TOKEN_SECRET_KEYใส่ค่าใน secret manager; อย่าเปลี่ยนชื่อโดยไม่แจ้ง deploy
ห้ามรีบลบ @Public() บน getOrgUnit / list โดยไม่ inventory callerต่างจาก getEmployeeSalary ที่ ROI #1 ชัด

F · 2way-api — สิ่งที่อย่าทำปน PR backdoor

ที่มา: 2way-api/04

ทำใน 90 วันอย่าปนใน PR เดียวกัน
ลบ i3admin blockลบ dead modules ทั้งก้อน (QUAL)
ลบ secret fallbackรวม Node + package manager (QUAL-04/05)
ignoreExpiration: falseredesign โครง announce ทั้งหมด
Parameterized SQLเปลี่ยนชื่อ column ใน MSSQL

คุย frontend/LINE ก่อน ถอด @Public() บน complaints / LINE / announce mutations (SEC-2WAYAPI-04) — การถอดถูก แต่ timing ต้องมี client พร้อมส่ง JWT


G · Shared platform contracts (ข้าม repo)

สัญญาConsumerหมายเหตุ
Device apiKeyAPP_TYPE (WEB, WEB_ADMIN, MOBILE, …)ทุก legacy frontend + vtrc-api configเปลี่ยนค่า key = rotate; เปลี่ยนชื่อ header กระทบทุก client
GraphQL endpoint จาก checkLinkURL() / window.location.hrefvtrc-web apollo configอย่าเปลี่ยนเป็น .env-only โดยไม่ dual-support
SECRET_KEY ชื่อตัวแปร ชุด domain Nestbenefit / recruitment / ai-recruitment / pmsเปลี่ยนค่าพร้อมกันได้; เปลี่ยนชื่อต้องพร้อม pipeline ทุกตัว
Buddhist year ใน UIweb + backofficeอย่าบังคับ CE ปี ค.ศ. ใน form HR โดยไม่ผ่าน product

H · Decision matrix — เมื่อไหร่ถึงจะ "rewrite ชื่อ"

ใช้ตารางนี้ก่อนเปิด rename PR:

คำถามถ้าคำตอบเป็น "ไม่"
มี inventory ทุก consumer (code + DB + env + FMIS + mobile) ครบหรือยังหยุด
มี dual-read / dual-write ช่วงเปลี่ยนหรือยังหยุด
มี rollback ที่ไม่ต้อง restore DB จาก backup หรือไม่หยุด
PR นี้มี security fix อื่นปนอยู่หรือไม่แยก PR
ผ่าน 19.1 DoD แล้วหรือยัง (ถ้าเป็น cosmetic)เลื่อนหลัง emergency

I · สรุปสั้นสำหรับ reviewer

เมื่อ review PR ที่อ้าง Vol 19:

  1. ถ้าแตะรายการในตาราง A–D → ขอ decision doc หรือ reject
  2. ถ้าลบ @Public() → แยก dropdown vs write/PII
  3. ถ้าแก้ typo ภาษาอังกฤษในชื่อไฟล์/ENUM → ถามว่า migration พร้อมหรือยัง
  4. ถ้า "cleanup ตอนแก้ security" → ขอแยก commit/PR

Modernization ที่ดีคือ เปลี่ยนพฤติกรรมอันตราย โดยคงสัญญาที่โลกภายนอกพึ่ง จนกว่าจะมีโครงการย้ายสัญญาอย่างจงใจ

/ Good modernization changes dangerous behavior while keeping external contracts stable until an intentional contract-migration project exists.