Files
imphnen-backend-service/docs/dev-audit-findings.md
T

3.8 KiB

Dimentorin — Catatan Temuan Infra (Dev Audit, 2026-08-04)

Dokumen ini mencatat temuan yang membutuhkan perhatian tim sebelum produksi. Semua diuji lokal (Postgres dimentorin, backend :4099).

1. SMTP email verification broken (blocker aktivasi user baru)

  • Endpoint POST /v1/iam/auth/send-otp gagal: SMTP transport error (535): Username and Password not accepted — kredensial .env (SMTP_EMAIL=dev@example.com, SMTP_PASSWORD=dev) ditolak Google SMTP.
  • POST /v1/iam/auth/verify-email tetap butuh OTP untuk memanggil, tapi lihat poin 2.
  • Dampak: mentee/mentor baru tak bisa menerima OTP lewat email → tak bisa aktivasi → tak bisa login, kecuali via verify-email langsung.
  • Diperlukan: SMTP credential institution yang valid (Gmail App Password atau SMTP relay), sebaiknya dari BWS secret management, bukan hardcode.

2. FIXED — verify-email TIDAK memverifikasi OTP (security issue)

Status: FIXED di branch feat/dimentorin-postgres (2026-08-04).

imphnen-iam/src/auth/application/mod.rsverify_email():

  • OTP sekarang dipersist ke tabel app_otp_cache (entity baru imphnen-entities/src/seaorm/common/otp_cache.rs, resource app_otp_cache sudah direncanakan di ResourceEnum::OtpCache).
  • register() & resend_otp() menyimpan otp_hash + expires_at setelah email terkirim (kalau email gagal, tidak ada OTP yatim / OTP lama tidak di-overwrite).
  • verify_email() memanggil OtpManager::validate_otp_hash(stored_hash, expires_at, payload.otp) sebelum set is_active. validate_otp_hash ditambahkan ke OtpManager (pure hash+expiry tanpa perlu plaintext code).
  • OTP single-use: di-delete setelah verifikasi sukses. Reuse / OTP tanpa cache / OTP expired semua ditolak (400).
  • Uji lokal (Postgres, :4099): OTP salah → 400 "Invalid or expired OTP", user tetap inactive; OTP benar → 200 "Email verified successfully", user aktif, OTP dihapus; verify ulang → 400 "User already active"; email tanpa OTP → 400 "No OTP issued".
  • Tabel dibuat via SQL manual (create_schema.rs ditambah otp_cache untuk bootstrap penuh).

3. (OK, sudah benar) Register mentor + booking

  • POST /v1/dimentorin/mentors/create → 200, user + mentor profile dibuat, status pending, user tak tampil di list public sampai verified.
  • POST /v1/dimentorin/mentors/{id}/sessions/create → 200, session pending.
  • Kedua endpoint fungsional setelah fix UUID (commit 9b5efef).

Rekomendasi

Tangani #1 dan #2 sebelum go-live. #2 adalah kelas bug "OTP di-generate tapi tak dipakai" — sisi verifikasi email saat ini tidak lebih dari form "set is_active=true tanpa autentikasi".

4. DONE — Payment flow (alur bisnis menjual)

Status: DONE di feat/dimentorin-postgres (2026-08-05).

  • Tabel app_payments: amount (dari mentoring_rate mentor) + service_fee 2000 + total; method va/qris/manual; provider manual default (swap Midtrans/Xendit nanti — cukup ganti nilai provider dan implementasi generate_external_ref/notifikasi webhook).
  • Routes protected: POST /payments/sessions/{id}/create, GET /payments/me, GET /payments/{id}, POST /payments/{id}/confirm.
  • Guard: mentee hanya bisa akses payment miliknya (403 kalau bukan); confirm hanya Admin / Admin Pembayaran.
  • confirm_payment otomatis mengubah session terkait pending -> confirmed (loop bisnis lengkap: book -> bayar -> sesi terkonfirmasi -> feedback).
  • FE: PaymentStep pilih VA/QRIS, rate real dari mentoring_rate; modal appointment: book -> create payment -> tampil VA/QR dengan external_ref + total + expiry -> success. Service lib: postCreatePayment/getMyPayments/getPaymentById/postConfirmPayment.
  • E2E verified (lokal :4099): create VA dan QRIS, confirm 200, re-confirm 409, non-admin 403, akses payment orang lain 403, session auto-confirmed.
  • TODO produksi: isi kredensial payment gateway (Midtrans/Xendit) + webhook callback; SMTP masih blocker (#1).