Blog
Catatan teknis seputar web development, DevOps, dan integrasi AI.
500 artikel
- 22.30devops
Deploy Staging Dibekukan: Ritual Per-Commit Digantikan Tunnel
Port inbound buat deploy ditutup total: staging KotaPortal kini dilayani lewat tunnel outbound-only, tanpa ritual deploy per-commit.
TL;DR: Deploy staging tiap commit beneran hilang, bukan error—backend KotaPortal sekarang dilayani lewat Cloudflare Tunnel dari VPS, jadi nggak perlu job deploy lagi. Origin cukup punya koneksi outbound ke port 7844, port inbound boleh ditutup total, malah lebih aman. Frontend tetap pakai preview bawaan hosting, backend lewat tunnel, reviewer nggak perlu tahu bedanya.
#cloudflare#cloudflared#deployment - 21.26security
Mitigasi Kerentanan SSRF pada Next.js Image Optimizer
Konfigurasi remotePatterns wildcard menjadikan /_next/image proxy fetch terbuka. Pola penutupannya: local-only, satu host eksplisit, uji negatif.
TL;DR: Konfigurasi Next.js KotaPortal pakai wildcard hostname plus CSP img-src https global, alhasil endpoint /_next/image bisa jadi proxy terbuka rawan SSRF. Solusinya, remotePatterns dihapus total dan CSP dipersempit, host eksternal yang emang dibutuhkan ditambahin eksplisit satu-satu. Biar nggak balik lagi, ada tes otomatis yang mastiin URL asal dikasih 400, bukan 200.
#nextjs#next-image#ssrf - 12.51backend
Mengapa JWT Pengguna Terhapus Harus Mengembalikan 401, Bukan 500
Token JWT yang sah secara tanda tangan tetap bisa menunjuk pengguna yang sudah dihapus. Pengalaman memetakan sql.ErrNoRows ke 401 agar frontend membersihkan sesi.
TL;DR: Jadi token user yang udah dihapus masih nembak API terus, dan middleware balikin 500, bikin frontend nggak mau hapus sesi dan user dapet banner error doang. Perbaikannya gampang: cek errors.Is(err, sql.ErrNoRows), kalau usernya nggak ada balikin 401 biar frontend bisa purge sesi. Ini juga sesuai RFC 9110 dan 6750, error lain tetap 500.
#go#golang#jwt - 05.36backend
Pembayaran di Luar Sistem: Penanda, Bukan Modul
Fakta verifikasi dana di luar aplikasi dimodelkan sebagai dua kolom nullable: kontrak *bool wajib, 409 khusus, dan union SQL dua lengan.
TL;DR: Jadi begini, verifikasi denda rental emang dilakuin bendahara di luar aplikasi, jadi nggak perlu payment gateway. Cukup nambah dua kolom nullable, payment_marked sama payment_marked_at, di tabel pengajuan yang udah ada. Ada satu endpoint penanda yang idempoten, dikawal izin tulis, dan komplain ditolak 409.
#go#mysql#api - 05.30security
Jaringan Keamanan Mekanis yang Dirancang untuk Diam
Hook rahasia yang membedakan temuan dari error, CI yang mengumpulkan temuan tanpa merahkan build, dan ZAP mingguan yang skip dengan rapi.
TL;DR: Hook gitleaks suka bikin commit gagal cuma gara-gara error lingkungan, bukan bocoran beneran. Solusinya: blokir cuma kalau exit 1 plus laporan JSON valid, sisanya cukup peringatan. CI dan ZAP mingguan juga kalem, cuma ngumpulin temuan buat direview, nggak asal bikin build merah tanpa bukti nyata.
#security#gitleaks#github-actions - 05.22backend
Cek Benturan Jadwal sebagai Peringatan, Bukan Penghalang
Formulir peminjaman kini memperingatkan benturan jadwal tanpa memblokir: endpoint baca-saja, SQL irisan inklusif, debounce dan abort.
TL;DR: Dulu dua pengajuan sewa aula yang tabrak tanggal bisa lolos dua-duanya karena petugas beda nggak saling cek. Sekarang ada endpoint baca-saja yang nandain irisan jadwal, terus formulir munculin kotak peringatan kuning. Tapi tombol kirim tetap bebas, soalnya sistem cuma ngasih tahu, keputusan akhir tetap di tangan petugas.
#go#mysql#react - 04.35backend
Empat Kontrak di Balik Formulir Unggah Publik
Formulir multipart publik menegakkan empat kontrak sekaligus: enum tertutup, slot berkas kondisional, batas unggah, dan migrasi skema.
TL;DR: Gawatnya, form upload publik frm02 ternyata punya empat kontrak tersembunyi yang harus sinkron: enum di level aplikasi, file wajib cuma kalau syaratnya true, upload dipagin 10 MiB plus cek magic byte, dan migrasi ENUM yang aman saat rollback. Salah satu lapisan geser dikit, validasi langsung ribut. Intinya: jangan ubah satu kontrak sendirian.
#go#multipart#file-upload - 04.34backend
Lantai Hari Kalender, Bukan Truncate 24 Jam
Truncate 24 jam di Go bukan batas hari kalender; ini pola perbaikan yang aman untuk kolom DATE.
TL;DR: Jadi ceritanya tanggal pengajuan sewa kegeser satu hari gara-gara pakai time.Truncate(24 jam) yang ternyata bukan buat nyari tengah malam lokal, tapi kelipatan 24 jam dari zero time Go. Ditambah driver MySQL otomatis konversi ke UTC, makin kacau. Solusinya ekstrak y, m, d, terus bangun ulang pakai time.Date dengan UTC eksplisit.
#go#mysql#timezone - 01.30security
Ketika Server Fail-Closed, Antarmuka Pun Harus Jujur
Server menolak unggahan bebas dari editor ter-scope, tetapi tombolnya tetap ditawarkan. Gate antarmuka menertibkan affordance; penegakan tetap di server.
TL;DR: Jadi gini, editor yang cuma punya akses terbatas masih bisa lihat tombol upload media, padahal pasti kena 403 karena server emang cuma izinin admin-global. Server-nya sih udah aman fail-closed, masalahnya di UI, jadi tombolnya disembunyiin pakai gerbang canManageModule, niru pola canUploadFree. Intinya UI cuma cerminan aturan server, bukan penegak keamanan beneran.
#rbac#react#ux