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

47 lines
3.9 KiB
Markdown
Raw Normal View History

# 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) — ✅ FIXED (2026-08-05, Google App Password)
- 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.rs``verify_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
2026-08-05 09:32:37 +07:00
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).