
Jul 25, 2025
RBAC yang Waras (Biar Gak Bocor Data)
Bug permission itu tipe bug yang bikin orang berkeringat tanpa olahraga. Sekali salah, efeknya bisa dari “fitur kok hilang?” sampai “lah ini data siapa?” yang langsung naik level jadi incident.

Maarif Alawi
Full-Stack Web App Developer
RBAC itu mahal kalau salah, karena cost-nya bukan cuma dev time. Cost-nya trust, support chaos, dan rasa was-was tiap deploy. Dalam 3 tahun dan ~13 project shipped, RBAC yang rapi itu salah satu pembeda antara app yang nyaman dipakai vs app yang bikin tim takut buka dashboard.
Cerita singkat: tombol muncul, tapi data ketolak, dan tenant hampir ketuker
Pernah ada kasus user role “Viewer” bisa lihat tombol “Edit” karena UI ngambil state permission dari cache lama. Begitu diklik, API nolak 403, jadi user bingung dan ngegas.
Lebih parahnya, ada query yang hampir ngambil data lintas tenant gara-gara satu endpoint lupa filter tenant_id. Untungnya ketahuan cepat karena log error di Sentry nunjukin request aneh: user A akses project yang bukan tenant-nya.
Lesson-nya jelas: permission harus satu sumber, konsisten antara UI dan API. Dan tenant isolation itu bukan “nanti aja”, itu default hidup.
RBAC Minimal yang Kepake
Tiga role yang biasanya cukup buat banyak produk:
Admin: manage users/roles, semua akses, termasuk settings.
Editor: bisa create/update data, tapi gak bisa atur role/tenant.
Viewer: read-only, gak boleh ngubah apa pun.
Contoh 5 permission yang realistis:
projects.readprojects.writemembers.managesettings.updatebilling.view
Mini permission matrix (kecil aja, tapi jelas):
Kuncinya bukan bikin role banyak-banyak. Kuncinya: permission jelas, naming konsisten, dan gak ada “special case” liar.
UI ≠ Security
Hide button itu cuma UX, bukan security. User masih bisa call API langsung pakai Postman atau script, dan mereka gak peduli tombolmu invis.
Security harus ditegakkan di API dan DB. Kalau kamu pakai Supabase, manfaatkan RLS dan pastikan endpoint server juga ngecek role/permission sebelum query.
Tenant Isolation
Multi-tenant itu intinya satu: semua data punya tenant_id. Rule-nya simpel tapi brutal: setiap query harus selalu filter by tenant.
Jangan berharap “frontend pasti ngirim tenant yang bener”. Ambil tenant dari session/claims, lalu enforce di server dan di RLS.
Kalau ada satu endpoint lupa filter tenant_id, itu cukup buat bikin data bocor. Dan kamu bakal “belajar” dengan cara yang mahal.
Anti-patterns permission yang bikin bahaya
Percaya client-side checks doang karena UI “udah ngunci”.
Solusinya: enforce permission di API + RLS Supabase.Logic permission nyebar di 20 file dengan versi beda-beda.
Solusinya: satu permission helper, satu mapping role→permissions.Gak ada audit trail untuk perubahan role/akses.
Solusinya: log aksi sensitif (role update, invite revoke) ke audit_events.Query lupa tenant filter karena “udah aman kok”.
Solusinya: default scopetenant_iddi semua query server, dan tes untuk itu.
Kode: Next.js API route enforce permission + tenant filter
COPY THIS
Role dibatasi sedikit (Admin/Editor/Viewer) dulu, jangan kebanyakan
Permission naming konsisten (
resource.action)Ada matrix role→permission yang kecil dan jelas
UI cuma reflect permission, bukan jadi sumber security
API selalu cek permission sebelum query/mutate
Semua tabel multi-tenant punya
tenant_idSemua query server selalu
.eq("tenant_id", tenantId)Tenant diambil dari session/claims, bukan input user
Supabase RLS aktif untuk table sensitif
Aksi sensitif (role/invite/setting) dicatat di audit log
RBAC yang waras bikin produk aman tanpa bikin dev takut sentuh codebase. Support juga lebih tenang karena masalah akses bisa ditrace, bukan ditebak.
Kalau permission kamu rapi, kamu bisa scaling fitur tanpa scaling rasa panik.
