BigStarter
Database

Model Keamanan

Boundary keamanan lapisan data — otorisasi application-layer, tenant scoping, RLS sebagai defense-in-depth, dan canonical billing ownership.

Model Keamanan

Boundary Utama: Application-Layer

Untuk semua ORM dan semua host PostgreSQL, otorisasi dan isolasi tenant ditegakkan di lapisan aplikasi:

  • Permission check sebelum query — setiap oRPC procedure memeriksa permission (requirePermission, adminProcedure) sebelum menyentuh data.
  • Tenant scoping di dalam query — setiap operasi membawa tenant_id (atau billing_account_id) sebagai predicate SQL, di semua variant ORM.
  • Client hanya lewat oRPC — browser tidak punya jalur langsung ke database; DATABASE_URL bersifat privileged dan tidak pernah boleh terekspos ke sisi client.

RLS: Defense-in-Divide Berbasis Capability

RLS tetap didukung dan direkomendasikan sebagai lapisan kedua ketika host mendukung (Supabase). Namun akses data tidak pernah bergantung pada:

  • impersonasi JWT per-request (set_config('request.jwt.claims', ...)),
  • auth.uid() di jalur data,
  • role authenticated.

Alasannya: dengan koneksi ORM langsung (Drizzle/Prisma), boundary yang andal dan portabel adalah aplikasi — bukan mekanisme spesifik provider. Metadata ketersediaan RLS diekspos lewat resolveDatabaseCapabilities untuk fitur yang ingin memanfaatkannya secara opsional.

Canonical Billing Ownership

Tabel ledger billing (subscriptions, transactions, invoices, payment_orders, refunds, dst.) memakai model canonical ownership:

  • billing_account_id adalah sumber kebenaran pemilik.
  • tenant_id / user_id tetap ada sebagai mirror kompatibilitas, disinkronkan otomatis oleh trigger sync_billing_record_owner — jangan pernah diisi manual oleh kode aplikasi.
  • initiated_by_user_id mencatat aktor aksi.

Idempotensi Webhook

Webhook pembayaran diproses race-safe lewat RPC claim_webhook_event: satu event hanya diproses sekali; event gagal otomatis bisa di-reclaim oleh retry provider. State-nya (processing → processed | failed) dikelola di tabel webhook_events.

Invarian di Database

Operasi dengan risiko konsistensi tinggi — ledger kredit billing (grant/reserve/finalize/release), redeem kupon, pembuatan billing account — hidup sebagai fungsi SQL SECURITY DEFINER dan hanya bisa dipanggil lewat method contract yang typed. Kode aplikasi tidak pernah menulis ledger secara manual.