Skip to content

2way-meeting-backoffice — Scorecard

Legend:

  • 🔴 Critical = active security/data-loss/availability risk
  • 🟡 High = correctness/maintainability hazard, real impact
  • 🟢 Medium = friction/hygiene, ยังไม่เป็นอันตรายทันที

ทุกแถวอ้างโค้ดบน branch prod


Health table

IDSeverityคำอธิบายหลักฐาน (file:line)การแก้ไขที่เสนอ
SEC-2WAYMTBO-01🟡 HighJWT เก็บใน localStorage (ไม่ใช่ httpOnly cookie) — เสี่ยงขโมยผ่าน XSSutils/auth.tsx:7-11, fetchApiWithAxios.tsx:8, withAuthVerify.tsx:19httpOnly cookie + CSRF หรืออย่างน้อย CSP ที่เข้มขึ้น (ปัจจุบัน connect-src *)
SEC-2WAYMTBO-02🟡 HighRoute guard เป็น client-side หลัง mount — หน้า L2 render ได้ก่อน verify เสร็จ; ความปลอดภัยจริงอยู่ที่ backendwithAuthVerify.tsx:16-63, _app.tsx:152Next middleware หรือ SSR session check ก่อนส่ง HTML/data
SEC-2WAYMTBO-03🟡 HighSentry DSN ถูก hardcode เป็น fallback ใน client และ server config — commit ใน gitsentry.client.config.js:7-10, sentry.server.config.js:7-10ลบ fallback; บังคับอ่านจาก env เท่านั้น; rotate DSN ถ้าเคยหลุด
SEC-2WAYMTBO-04🟡 HighLogin พึ่ง 2way-api /api/v1/auth ซึ่งมี backdoor credential ฝั่ง backend (SEC-2WAYAPI-01)Login/components/Form.tsx:97-99แก้ที่ 2way-api เป็นหลัก; ฝั่ง UI อย่าพึ่ง "security by obscurity"
SEC-2WAYMTBO-05🟢 MediumBypass login รับ Bearer จาก query path แล้วแลก token — ถ้า token หลุดจาก email/link จะเข้า ChatCenter ได้bypassLogin/[token].tsx:34-57TTL สั้น + one-time use ฝั่ง API; อย่า log token
CORR-2WAYMTBO-01🟡 HighfetchAPI ไม่มี branch สำหรับ HTTP DELETE แต่ deleteAnnouncesContentId เรียก "DELETE" — คำสั่งลบประกาศผ่าน wrapper นี้จะไม่ยิง requestfetchApiWithAxios.tsx:17-65, services/announces.tsx:73-78เพิ่ม DELETE ใน wrapper หรือเปลี่ยนไปใช้ method ที่รองรับ
CORR-2WAYMTBO-02🟡 HighwithAuth เช็ค statusCode === 201 แต่ withAuthVerify (ตัวที่ active) เช็ค !== 200 — ถ้าสลับ HOC หรือ backend เปลี่ยน code จะได้พฤติกรรมคนละแบบwithAuth.tsx:41, withAuthVerify.tsx:38รวมเกณฑ์เป็นค่าเดียวที่ตรงกับ 2way-api จริง
CORR-2WAYMTBO-03🟢 MediumProblem/Detail เรียก path /createQuestion มีช่องว่างท้ายสตริงfeatures/2way/Problem/Detail/index.tsx:147ตัด whitespace; เพิ่ม regression test
CORR-2WAYMTBO-04🟢 MediumgetChatDetail hardcode roomEmpCode ค่าคงที่ — ใช้ดูห้องอื่นไม่ได้services/chat-center.tsx:6รับ parameter จริง; หรือลบ dead code ถ้าไม่ถูกเรียก
QUAL-2WAYMTBO-01🟢 Mediumชื่อ repo มีคำว่า meeting แต่ไม่มีฟีเจอร์ประชุม / ไม่เรียก meeting-vtrc-apifeature folders + next.config.js:38-39 basePath: "/2way-backoffice"เปลี่ยนชื่อหรือ README สั้น ๆ ที่ root ชี้แจง
QUAL-2WAYMTBO-02🟢 MediumAPI error ถูก resolve(error) + console.log ใน services — UI มักเงียบเมื่อ backend ล่มfetchApiWithAxios.tsx:35-40, surveys.tsx:8-10,116-118reject จริง + toast/error boundary
QUAL-2WAYMTBO-03🟢 MediumMaterial-UI v4 + MUI v5 ปนในโปรเจกต์เดียวpackage.json:23-27migrate เป็น MUI v5 อย่างเดียว
QUAL-2WAYMTBO-04🟢 MediumignoreDuringBuilds (ESLint) + ignoreBuildErrors (TypeScript) — production build ผ่านได้ทั้งที่ type/lint พังnext.config.js:25-36เปิดกลับทีละส่วน; กัน regression ใน CI
QUAL-2WAYMTBO-05🟢 Mediumไฟล์ backup จำนวนมาก (* copy*, *_old*, .bk, ChatCenter2) ทำให้ค้นหา source of truth ยากเช่น HOC/withAuth copy.tsx, ChatCenter/index copy.tsxย้ายออกจาก src/ หรือลบหลังยืนยันไม่ถูก import
QUAL-2WAYMTBO-06🟢 Mediumservices/feedback.tsx ว่าง — logic ฝังใน component ยาวมากservices/feedback.tsx (0 bytes), Feedback/Edit/components/Form.tsxสกัดเป็น service module ให้สอดคล้อง announces/surveys
QUAL-2WAYMTBO-07🟢 MediumwithAuthSuperAdmin ไม่ได้เช็ค level === 1 ทั้งที่ชื่อบอก super adminHOC/withAuthSuperAdmin.tsx:8-14 vs auth.tsx:71ใช้ getUserInfo().isSuperAdmin หรือลบ HOC ที่ทำให้เข้าใจผิด
LEG-2WAYMTBO-01🟢 MediumNext.js 12 + React 17 — EOL ด้าน security patch ของสาย majorpackage.json:44,47วางแผน upgrade Next 14+/React 18 เมื่อมี capacity
LEG-2WAYMTBO-02🟢 Mediumenzyme + jest setup สำหรับ React 17 — ecosystem หยุดนิ่งpackage.json devDeps, __test__/ย้ายไป React Testing Library เมื่อ upgrade React
OBS-2WAYMTBO-01🟢 Mediumชื่อ env appConnectChatAPI ชี้ 2way-vtrc-api ไม่ใช่ chat-center — debug ข้าม repo สับสนnext.config.js:57, .env.production:9เปลี่ยนชื่อเป็น appConnectVtrcApiLegacy (breaking — ต้อง sync ทุก call site)
OBS-2WAYMTBO-02🟢 MediumSentry webpack plugin ปิด → source map จาก pipeline นี้อาจไม่ขึ้น; แต่ runtime init ยังส่ง event ที่ tracesSampleRate: 1.0next.config.js:79-80, sentry.client.config.js:12เปิด withSentryConfig อย่างถูกต้อง หรือปิด init ถ้าไม่ใช้; ลด sample rate
OBS-2WAYMTBO-03🟢 MediumCSP ใน _app อนุญาต connect-src * และ wss host ไม่ตรง env websocket (vtrcapi vs vtrc)_app.tsx:126-129, .env.production:11จำกัด allowlist ตาม env จริง
OBS-2WAYMTBO-04🟢 MediumProduction mute console.log/error/warn ทั้งก้อน — ทำให้นักปฏิบัติการ debug จาก browser ยาก และอาจกลบสัญญาณ error_app.tsx:55-58mute เฉพาะ log ระดับ debug; คง console.error หรือส่งเข้า Sentry

สรุปเชิงภาพรวม

repo นี้ไม่มี business logic สำคัญฝั่ง server — debt Critical ส่วนใหญ่จึง อยู่ที่ backend ที่เรียก (2way-api, 2way-vtrc-api, chat-center-api) ไม่ใช่ที่ Next process เอง

ข้อค้นพบที่ควรยึดเป็น canonical truth:

  1. ชื่อ "meeting" ใน repo ไม่เกี่ยวกับ Meeting Platform
  2. LIFF พนักงาน → 2way-vtrc-api; แอดมิน CRUD หลัก → 2way-api; ChatCenter → chat-center-api + WS
  3. Group/approver admin ใน UI นี้ = teamAdmin (chat) + survey adminApprove + complaint multi-step — ไม่ใช่ meeting approver
  4. Sentry มีไฟล์ config และ _error capture แต่ webpack plugin ถูกปิด และ DSN hardcode
  5. Build artifact ที่ deploy จริงคือ .next ใน Docker (Dockerfile) ไม่ใช่โฟลเดอร์ out/ จาก next export (แม้ script จะมี)

Checklist ก่อนเปลี่ยนโค้ดใน repo นี้

  1. ยืนยันว่าเรียก backend ตัวไหน (appConnectAPI vs appConnectChatAPI vs appConnectChatCenterAPI)
  2. ถ้าแตะ auth — อ่านทั้ง withAuthVerify และ response statusCode จริงจาก 2way-api
  3. ถ้าแตะ ChatCenter — ตรวจทั้ง REST และ websocket path /chat-center-ws/socket.io
  4. อย่าลบไฟล์ *_copy* / *.bk โดยไม่ grep import ก่อน
  5. หลังแก้ API wrapper — ตรวจว่า method ที่เรียก (รวม DELETE) ถูก implement จริง