D
Engineering

Tech Debt Roadmap

10 known issues dari CONTEXT.md — MongoClientCrm nil, DB split-brain, JWT algo tidak di-pin, CORS, password ter-log, GetJwtClaims panic, dead code, DI bypass, PM2 bug. Diurutkan risiko.

Daftar known issues backend-go dari CONTEXT.md. Diurutkan risiko rendah → tinggi, bukan berdasarkan seberapa mengganggu. Tujuan: pembenahan tidak menghentikan pengiriman fitur.

Aturan utama: Jangan gabungkan pembenahan dengan fitur dalam satu commit. Pisahkan agar mudah di-revert.


Tahap 1 — Dokumentasi & cleanup (nol risiko)

#ItemStatusLokasiCatatan
1Hapus dead code era GORM⬜ Belumhandlers/auth.go, contact.go, user.go, label.go, chat.go (bagian dead)Login pakai database.DB dormant. chat.go punya Payload struct aktif — jangan hapus
2Hapus model GORM legacy⬜ Belummodels/chat_inbox.go, chat_list.go, chat_outbox.go, user.go, paket.go, dll11 file. Setelah #1 selesai, tidak ada konsumen
3Hapus database/ package⬜ Belumdatabase/database.goConnectDB() dikomentari di main.go:43. Setelah #1 #2
4Hapus route komentar di routes.go⬜ Belumroutes/routes.go:121-15636 baris legacy SQL route + GORM endpoints

Tahap 2 — Jaring pengaman (risiko rendah)

#ItemStatusLokasiCatatan
5Test untuk handler kritis⬜ Belum—Prasyarat Tahap 3 & 4. Tidak ada test suite. Prioritas: CallbackMessage, SubmitMessage, VerifyToken
6Pasang linter (golangci-lint)⬜ Belum—Jalankan pada file baru dulu, jangan format ulang seluruh repo
7go vet ./... bersihkan⬜ Belum—Static analysis dasar

Tahap 3 — Fix krusial (risiko sedang, butuh test)

#ItemStatusLokasiCatatan
8Uncomment ConnectCrmDB() atau hapus route _crm⬜ Belummain.go:50-53, mongo/mongo.go:64#1 paling krusial. MongoClientCrm nil → semua route _crm panic. Pilih: enable CRM DB, atau hapus 16 route + 4 handler file
9Pin JWT algoritma ke HS256⬜ Belummiddlewares/authMiddleware.go:94-96Algorithm confusion risk. Fix: cek token.Method.(*jwt.SigningMethodHMAC) di keyfunc
10Fix IP allowlist — jangan trust header spoofable⬜ Belummiddlewares/authMiddleware.go:62-71X-Real-IP/X-Forwarded-For bisa di-set client. Fix: hanya trust RemoteAddr, atau pastikan reverse proxy menimpa header
11Fix CORS config⬜ Belummain.go:31,35AllowOrigins:"*" + AllowCredentials:true = browser reject. Pakai config.Env.AllowOrigins (sudah ada, dikomentari)
12Hapus log.Print(mongoURI)⬜ Belummongo/mongo.go:57URI berisi password tercetak ke stdout setiap startup
13Fix GetJwtClaims type assertion⬜ Belumutils/utils.go:67c.Locals("user") simpan jwt.Claims, bukan *jwt.Token. Assertion akan panic. Fix: c.Locals("user").(jwt.MapClaims) langsung
14Hilangkan DB name split-brain⬜ Belumhandlers/environtment.go:6 vs internal/service/chat_service.go:84,112Handler pakai const DBname, service pakai config.Env.DbName. Fix: gunakan config.Env.DbName konsisten

Tahap 4 — Struktural (risiko tinggi)

#ItemStatusPrasyaratCatatan
15Aktifkan repo DI atau hapus⬜ Belum#5chatService.chatRepo/userRepo di-inject tapi tidak dipakai (chat_service.go:84,112 akses Mongo langsung). Pilih: refactor service pakai repo, atau hapus layer DI
16Konsolidasi 3 tenant ke route param⬜ Belum#5, #8Hilangkan 3x duplikasi handler (chat_live.go + _admin.go + _crm.go). Tenant via path param + resolver. Risiko tinggi — sentuh semua route
17Pusatkan URL service ke config⬜ Belum—EngineUri, EngineUriCRM, EngineBot hardcoded di handlers/environtment.go. Pindahkan ke .env via Viper. Lihat External Services
18Fix PM2 first-start bug di CI⬜ Belum—.github/workflows/deploy_production.yml:60 pakai $PROJECT_DIR_PRODUCTION (GitHub vars, bukan env shell). Saat PM2 first-start, path resolve gagal. Fix: export var atau hardcode path

Detail issue terpilih

#8 — MongoClientCrm nil (paling krusial)

main.go:50-53:

go
//err = mongo.ConnectCrmDB()
//if err != nil {
//    log.Fatal("Error connecting to MongoDB:", err)
//}

mongo.MongoClientCrm nil. Semua handler _crm yang memanggil mongo.MongoClientCrm.Database(crm_dazo).Collection(...) akan nil-pointer panic.

Opsi:

  1. Uncomment + sediakan MongoDB crm_dazo terpisah
  2. Hapus 16 route _crm (routes.go:97-115) + 4 handler file (chat_callback_crm.go, chat_live_crm.go, chat_submit_crm.go, broadcast_crm.go)

#9 — JWT algorithm confusion

authMiddleware.go:94-96:

go
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    return []byte(config.Env.JwtSecret), nil
})

Tidak memeriksa token.Method. Token dengan algoritma lain (RS256, none) bisa lolos.

Fix:

go
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
        return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
    }
    return []byte(config.Env.JwtSecret), nil
})

#13 — GetJwtClaims panic

utils/utils.go:66-67:

go
func GetJwtClaims(c *fiber.Ctx) JwtClaims {
    token := c.Locals("user").(*jwt.Token)   // BUG

authMiddleware.go:107 menyimpan token.Claims (tipe jwt.Claims), bukan *jwt.Token.

Fix:

go
claims := c.Locals("user").(jwt.MapClaims)
sub := int(claims["sub"].(float64))

Saat ini tidak ada handler aktif yang memanggil GetJwtClaims — hanya dead code handlers/auth.go:78. Tapi helper ini siap dipakai dan akan panic bila dipanggil.

Status legend

  • ⬜ Belum — belum dikerjakan
  • 🔄 Sedang — dalam progress
  • ✅ Selesai — selesai

Langkah berikutnya