Lewati ke konten utama

Order Service — Keamanan & Hardening

Semua item di bawah telah diimplementasikan dan diverifikasi per audit keamanan 2026-05-29–2026-06-05.


Autentikasi & Otorisasi

  • Validasi kepemilikan order di handleConfirmReceipt: Handler memverifikasi bahwa MerchantID pada order yang diminta sama dengan subject dari JWT sebelum melanjutkan proses. Mencegah merchant A mengkonfirmasi penerimaan order milik merchant B.

  • Validasi kepemilikan order di handleShipping: Handler memverifikasi MerchantID pada parent order terhadap subject dari JWT sebelum mengembalikan data atau memproses perubahan. Mencegah akses lintas-merchant pada data pengiriman.

  • Validasi kepemilikan order di handleStartPayment: subject dari JWT diteruskan ke layer store (store.StartPayment) dan ownership di-enforce di sana. Memastikan validasi tidak bisa di-bypass meski handler dimodifikasi di masa depan.

  • JWT wajib memiliki exp claim: parseJWTSubject menggunakan jwt.NewParser dengan opsi WithExpirationRequired(). Token tanpa field exp ditolak secara eksplisit — token debug, credential yang bocor, atau token buatan tanpa expiry tidak akan pernah diterima.

  • JWT wajib memiliki issuer yang sesuai: Parser dikonfigurasi dengan jwt.WithIssuer(issuer) menggunakan nilai dari env var JWT_ISSUER (default: kesles-merchant-auth). Token HS256 dari sistem lain yang kebetulan berbagi secret yang sama — misalnya environment staging — akan ditolak karena issuer-nya tidak cocok.


Validasi Input & Batas Data

  • Startup gagal jika INTERNAL_API_KEY kosong di production: Config melakukan log.Fatal saat variabel ini tidak diisi di environment production. Mencegah endpoint /internal/* order management menjadi terbuka secara diam-diam tanpa autentikasi.

  • Field amount divalidasi non-negatif di handleCreateOrder: unit_price_amount, shipping_fee_amount, dan promo_amount divalidasi >= 0 (nilai negatif ditolak dengan bad request). Mencegah nilai negatif memanipulasi kalkulasi total order.

  • Harga diambil dari server saat offer code valid: Ketika offer_code dikirim oleh klien, handleCreateOrder mengambil quotation aktif dari server dan menggunakan harga dari sana — mengabaikan sepenuhnya nilai unit_price, shipping_fee, dan promo_amount yang dikirim klien. Price manipulation via request body tidak dimungkinkan.

  • photo_url divalidasi scheme HTTPS di handleConfirmReceipt: Sebelum diproses, URL foto bukti penerimaan (jika dikirim) di-parse dan ditolak bila scheme bukan https. Mencegah penyimpanan URL non-HTTPS pada konfirmasi penerimaan barang.

  • Status pengiriman divalidasi terhadap allowlist: UpdateShippingStatus hanya menerima nilai dari set yang telah ditentukan: not_processed, packed, in_transit, delivered, returned. String status arbitrer dari caller ditolak sebelum disimpan ke database.


Reliabilitas & Konsistensi Data

  • Panic recovery middleware aktif: Server membungkus mux dengan withRecovery middleware. Panic di dalam handler tidak lagi menyebabkan goroutine crash tanpa respons — klien tetap menerima HTTP 500 dan service tetap berjalan.

  • AcceptTerms dan StartPayment berjalan dalam satu transaksi database: Method AcceptTermsAndStartPayment membungkus kedua operasi dalam BeginTx/Commit dengan defer tx.Rollback(). Jika StartPayment gagal setelah AcceptTerms berhasil, field terms_accepted_at tidak akan tersisa tersimpan di database — tidak ada state korup parsial.