Sistem operasional bank · on-prem · Indonesia-first
Warkat masuk, uang ketemu,
buku terkunci.
Orivo adalah platform order-to-cash & pengelolaan warkat untuk bank dan lembaga pembiayaan Indonesia: intake cek/bilyet giro, kliring & penagihan, PDC/CDC, dispatch pembayaran, rekonsiliasi berbasis toleransi, dan kontrol dual-authorisation yang ditegakkan di database — bukan hanya disembunyikan di tombol UI.
- ✓7 status warkat dengan mesin peralihan (state machine) —
Realized,Lodged,Hold,Return,Destroyed,Recovered,Misplaced— lengkap dengan warkat fisik (lodgement) & bukti (image) yang menempel. - ✓Setiap klaim di halaman ini punya angka uji. 184 pemeriksaan SQL + 101 uji Java + 292 uji aplikasi (175 smoke end‑to‑end · 69 penolakan lapis gap · 48 harness tampilan jsdom) + 14 uji migrasi skema — dijalankan ulang oleh satu perintah per lapis; kalau ada pemeriksaan yang hilang, gerbangnya merah.
- ✓RPO diikat, bukan diklaim. Arsip WAL dipantau sebagai kontrol hidup + alert; pernah macet 75× di lingkungan uji tanpa satu pun gerbang lain protes — sekarang tidak bisa lagi.
Kenapa halaman ini ada
Empat hal yang menggerus margin operasional back-office
Semuanya bisa dihitung, dan keempatnya ada di sistem yang masih berjalan di atas spreadsheet, WhatsApp grup, dan "tolong cek rekening koran".
1Warkat tersesat di tengah jalan
Cek/BG diterima cabang, tidak jelas siapa yang pegang, jatuh tempo terlewat, retur tidak tertagih. Tanpa mesin status + bukti lodgement, "hilang" tidak bisa dibedakan dari "belum diproses".
Dampak yang bisa diukur: umur tunggakan (aging) membengkak, biaya penagihan ulang, dan sengketa nasabah yang memakan hari kerja.
2Rekonsiliasi = mencocokkan manual
Mencocokkan mutasi dengan 1,8 juta baris/hari secara visual menghasilkan dua kegagalan sekaligus: lambat, dan orang berhenti mempertanyakan kecocokan "yang hampir pas".
Yang dibutuhkan: pencocokan aturan + toleransi, antrean pengecualian (exception queue) yang punya pemilik, dan close yang bisa dibuktikan waktunya.
3Kontrol yang bisa dilewati
Maker-checker yang hanya berupa "tombol disembunyikan" akan dilewati saat ada yang masuk malam hari. otorisasi parameter, perubahan limit, dan akses darurat butuh penegakan di tempat data berada.
Orivo menaruhnya di PostgreSQL: pemicu/aturan penolakan di lapisan data + rantai hash audit, supaya bypass itu menjadi kejadian, bukan kemungkinan.
4"Siap produksi" yang tidak terbukti
Broswur sistem bank biasanya berisi kata: aman, andal, scalable. Tidak ada angka, tidak ada perintah untuk mengulanginya. Kami menulis keduanya — termasuk apa yang belum diukur.
Daftar "belum diukur" ada di bagian Bukti, karena daftar itu justru bagian dari tawarannya.
Sepuluh modul
Satu alur: warkat masuk → uang keluar → buku tertutup → audit terkunci
Modul boleh dibeli/dipakai bertahap; skema data & kontrolnya sudah satu alamat sejak hari pertama. Tanda di tiap kartu: apa yang sudah punya uji. Delapan kartu terakhir di bagian ini = modul yang belum ada, lengkap dengan fase & gerbang keluarnya — bukan daftar harapan kosong.
Penerimaan Warkat
Lodgement per bendel (batch), tangkap nomor warkat/EMKL/NRIC, nilai nominal, drawer/drawee, tanggal & tenor; unggah citra (image) warkat + QR/barcode bendel.
tujuh status mesin peralihan · idempoten per nomor warkat · maker ≠ checker ditegakkan.
Kliring & Penagihan
Klirim keluar/masuk, pencocokan berkas SKNBI, penanganan retur (alasan, biaya), dan penjadulan ulang penagihan tanpa membuat nomor warkat baru.
Alur retur diuji sebagai transaksi terpisah — bukan sekadar perubahan status.
Post-Dated & Safe-Keeping (PDC/CDC)
Penyimpanan warkat mundur-jatuh-tempo, penjadulan presentasi, peringatan H-3, perpanjangan/pengembalian, dan pencatatan biaya penitipan.
Aturan biaya & preferential pricing ikut modul referensi (M7).
Dispatch Pembayaran
Batch 5.000 item → file transfer/GIRO/RTGS/LLG, ack dalam ≤3 s per batch (SLO), pembalikan (reversal) sebagai transaksi baru, bukan edit.
Ledger posting diuji gagal-dulu-sukses-kemudian; saga punya kompensasi.
Rekonsiliasi & Kecocokan
Mutasi ↔ jurnal ↔ warkat dengan aturan toleransi (nominal/tanggal/kelipatan), pencocokan bertingkat, antrean pengecualian dengan pemilik & SLA, dan "close" yang punya stempel waktu.
Toleransi adalah parameter ber-dual-control — mengubahnya butuh otorisasi terpisah.
Maker-Checker & Parameter
Antrean otorisasi per peran, limit nilai, 4-eyes untuk perubahan parameter/limit/toleransi, break-glass berkedaluwarsa dengan tiket + tinjauan 24 jam.
Ditegakkan di DB: apply_parameter() menolak sebelum approval — ada uji penolakannya.
Referensi Hari-Nol
Nasabah, rekening, kantor cabang, produk & arrangement, bagasi tarif (charge rules), preferential pricing, kalender hari kerja/bursa, dan toleransi per produk.
◐ Skema ref.* sudah terpasang dan ditegakkan database: 10 pemeriksaan (006-refdata.sql + 007-refdata-verify.sql) — kalender hari kerja menolak menjawab tanpa data, tarif & toleransi butuh 4-eyes, dan batch hari-nol tidak bisa live selama laporan entitas yatim belum nol. Yang belum: service ecm-identity & layar muatnya.
Portal & Portlet Per Peran
Portlet yang dirakit per peran (teller/verifikator/autoriser/supervisor/audit/DPO), tampilan antrean, drill-down ke baris audit, dan mode baca-saja untuk auditor.
HTML5 SPA tanpa dependensi jaringan untuk fungsi inti; izin per portlet, bukan per menu.
Audit Rantai & Forensik
Log append-only dengan row_hash per baris + verifikasi rantai; pembuktian "tidak ada yang hilang diam-diam", dan kanal break-glass yang tetap tercatat.
UPDATE/DELETE pada tabel audit ditolak — diuji, bukan dijanjikan.
Statistik Lokal + Adapter LLM Opsional
Prioritisasi antrean pengecualian, deteksi anomali nominal/kedua-pihak, saran pencocokan — dihitung di lokal dengan statistik; adapter LLM hanya tambahan yang boleh mati.
Tidak ada jalur yang bergantung pada internet: adapter mati → modul tetap jalan penuh.
Delapan modul yang belum ada (diusulkan, bukan janji)
Diurutkan sesuai dependensi, bukan selera. Satu kartu = satu pertanyaan yang harus dijawab sebelum kode ditulis: tabel apa, endpoint apa, uji apa yang membuatnya berhenti jadi wacana.
Referensi hari-nol sebagai layanan
Master data nasabah/rekening/cabang/produk/arrangement/tarif/toleransi/kalender/kurs plus loader hari-nol
dengan laporan entitas yatim. Skemanya sudah jadi; yang belum adalah ecm-identity dan layarnya.
sebagian fase 1 · gerbang: 10/0 di 007 (sudah) +
loader idempoten dan uji yatim lewat API (belum)
Mata uang & revaluasi kurs
Kurs per tanggal sudah ada (ref.fx_rate); yang belum: perhitungan selisih kurs periodik dan
jurnal revaluasi berimbang. Bukan dealing atau treasury.
belum ada fase 4 · gerbang: 1.000 rekening × 3 kurs → selisih
ter-posting dan gl.chk_balance lolos; run ulang tidak menghasilkan jurnal ganda
Jembatan ke buku besar eksternal
Satu arah: jurnal keluar ke sistem akuntansi Anda, yang masuk hanya konfirmasi posting, plus peta akun. Ini pengganti yang jujur untuk "modul GL" — GL tetap punya satu pemilik.
belum ada fase 3 · gerbang: golden-file 3 target dan "peta akun bolong → export ditolak, bukan dikirim separuh"
Pengingat, tautan bayar, push
Surel/WhatsApp untuk penagihan, QRIS/VA sebagai opsi pelunasan, push ke antrean otorisasi. Kanal keluar saja — bukan gateway pembayaran.
belum ada fase 4 · gerbang: idempoten per (item, template, hari); webhook bertanda tangan salah → 401; kredensial kanal tidak pernah muncul di log
Hak subjek data pribadi
Alur pdp_request: ekspor, penghapusan, anonimisasi — termasuk penolakan yang dibuktikan
(retensi/legal hold). Menutup gap G7.
belum ada fase 2–3 · gerbang: penolakan tercatat dan bisa dibuktikan; penghapusan tidak memutus rantai audit
Onboarding & bantuan in-app
Tur per peran, pusat bantuan terpasang, pesan galat yang menjelaskan cara lolos. Bukan chatbot — tidak butuh jaringan.
belum ada fase 2 · gerbang: tiap kode galat yang dipakai
005 punya topik bantuan (pemeriksaan silang baru, pola check-manifests.py)
Katalog konektor yang bisa dipasang sendiri
Yang realistis: 1 katalog dan 2–3 adapter dengan uji kontrak, bukan "puluhan integrasi". Kredensial terenkripsi dan bisa dirotasi.
belum ada fase 5 · gerbang: kontrak gagal → konektor
degraded dan jalur lama tetap jalan; uji Logback membuktikan rahasia tidak terbocor
Report builder berizin (read-only)
Pembatasnya bukan selera: hanya AST ter-whitelist di atas replika dengan statement_timeout.
Kolom bebas tetap tidak — itu pintu belakang aturan PII dan otorisasi.
belum ada fase 5 · gerbang: SQL mentah ditolak; kolom di luar
allowed_columns ditolak; query berat dipaksa ke replika
Fitur
Yang ada di dalam, dikelompokkan seperti orang memakainya
✅ tersedia & ada uji · ◐ tersedia sebagian (gap terbuka ditulis, tidak disembunyikan) · 🛠 desain tertimbang, belum dibangun.
Operasional warkat
- ✅ 7 status warkat + mesin peralihan berizin (transaksi ilegal ditolak, ada ujinya)
- ✅ Lodgement per bendel, citra warkat, bukti fisik, dan riwayat perpindahan tangan
- ✅ PDC/CDC: penyimpanan, presentasi terjadwal, H-3 reminder, perpanjangan, pengembalian
- ✅ Retur dengan alasan + biaya, dan penagihan ulang tanpa nomor warkat baru
- ✅ Idempotensi kunci bisnis (nomor warkat + cabang + tanggal) — retry tidak membuat duplikat
- ✅ Aging & kolektibilitas dengan kalender hari kerja/bursa Indonesia
Rekonsiliasi & pembukuan
- ✅ Pencocokan bertingkat: eksak → toleransi nominal → toleransi tanggal → aturan fuzzy berbobot
- ✅ Exception queue dengan pemilik, SLA, dan eskalasi otomatis
- ✅ Close rekonsiliasi ≤ 60 menit (SLO) dengan bukti stempel waktu per sesi
- ✅ Jurnal saldo-deferrable: ketidakseimbangan baru dinilai saat
COMMIT(dan itu diuji) - ✅ Materialized view untuk agregat —
SUM200rb baris = 26–33 ms, jadi agregasi real-time bukan pilihan - ✅ Reversal sebagai transaksi baru (bukan koreksi in-place)
Kontrol, keamanan, kepatuhan data
- ✅ Least privilege 4 peran DB (
ecm_app/ecm_readonly/ecm_migrator/ecm_dpo) + RLS pada jalur portal - ✅ MFA untuk peran autorisasi — penolakan tanpa MFA diuji
- ✅ Dual control untuk parameter, limit, toleransi; penolakan "approval belum ada" diuji
- ✅ Break-glass: wajib tiket, kedaluwarsa, dan tetap tercatat di rantai audit
- ✅ Katalog PII + masking di DB dan di log (masking lewat pemicu
ddl_command_end+ uji Logback nyata) - ◐ Envelope encryption teruji; KMS/HSM nyata masih gap (G3); kolom ciphertext masih
text(G4) - ◐ Device-binding policy teruji unit, belum dipasang di filter (G5)
- ◐ Hak subjek UU PDP: katalog & masking ada; report/erase masih gap (G7)
Inteligensi ("pintar")
- ✅ Skor prioritas pengecualian dari statistik lokal (frekuensi, selisih, umur, poladrawer) — jalan tanpa internet
- ✅ Saran pasangan rekonsiliasi dengan keyakinan + alasan yang bisa dibaca manusia
- ◐ Adapter LLM untuk ringkasan sengketa/draft memo: opsional, fail-open, timeout + batas byte
- ✅ Tidak ada fitur inti yang bergantung pada model: memutus adapter = fitur tetap penuh
- 🛠 Deteksi anomali "dua pihak yang sama sering bertemu" (kolusi) — butuh data historis produksi
Integrasi & backbone
- ✅ Outbox pattern + 18 topik Kafka (nama/partisi/retensi dibaca dari dokumen arsitektur, ada gerbang
--check) - ✅ Konsumer idempoten + DLT untuk pesan racun
- ✅ Cache/sesi di Valkey (bukan Redis) + ACL user, TLS, dan kebijakan eviction berbeda untuk sesi vs cache
- ✅ Keycloak OIDC (Authorization Code + PKCE, cookie sesi), validasi token dengan
DelegatingOAuth2TokenValidator - ✅ Impor mutasi: CSV/MT940/camt.053 + API bank (adapter per bank, kontrak diuji)
- 🛠 ISO 20022 pacs/camt penuh untuk kanal kliring (fase 4)
Operasi & pemulihan
- ✅ RPO ≤60 s diikat arsip WAL yang dipantau + alert
WalArchiveStalled - ✅ Drill PITR nyata dengan angka tercatat (restore siap 1 s, titik recovery tepat, rantai audit utuh)
- ✅ Replika melayani bacaan saat primary mati (dibuktikan di drill)
- ✅ Helm chart + 17 aturan manifest diperiksa di CI (
check-manifests.py) - ◐ SLO burn-rate multi-window;
/actuator/prometheusbelum dibuktikan lewat HTTP (G11) - 🛠 Chart belum pernah di-apply ke klaster nyata di lingkungan ini (G12)
Formulir
Delapan belas form, masing-masing dengan validasi & kontrol yang bisa disebut namanya
Form di Orivo bukan "kolom isian": tiap form memegang kunci idempotensi, aturan validasi yang sama di klien & di database, dan titik otorisasi kalau risikonya menuntutnya.
| Form | Modul | Field kunci | Validasi & kontrol | Status setelah simpan |
|---|---|---|---|---|
| Penerimaan Warkat (Lodgement) | M1 | cabang, bendel, jenis (Cek/BG/SR), nomor warkat, EMKL/NRIC, drawer–drawee, nominal, tanggal surat, tanggal jatuh tempo | nomor 7 digit & unik per cabang; nominal > 0; tanggal surat ≤ jatuh tempo; idempoten pada kunci (nomor+ cabang + tanggal); maker ≠ checker | Lodged → antrean verifikasi |
| Verifikasi Citra & Data Warkat | M1 | citra depan/belakang, hasil OCR, koreksi manual, tanda tangan, alasan ketidaksesuaian | citra wajib; selisih OCR vs input butuh konfirmasi 2 langkah; semua koreksi tercatat di audit | Verified / Hold |
| Otorisasi (Maker-Checker) | M6 | antrean, ringkasan diff, alasan, token MFA | peran autorisasi wajib MFA; self-approval ditolak di DB; tiket tertaut untuk break-glass | status maju + kejadian audit Authorized |
| Penahanan (Hold) | M1 | alasan, penanggung jawab, tanggal tinjau ulang, catatan nasabah | tanggal tinjau > hari ini; tidak bisa dibuat oleh checker yang sama dengan verifikator | Hold (menghitung aging) |
| Retur Kliring | M2 | kode alasan, nominal retur, biaya, bukti fisik | kode harus ada di daftar; retur = transaksi baru (bukan edit); penagihan ulang mewarisi nomor warkat | Return → penjadulan ulang |
| PDC/CDC Titipan | M3 | penitip, rekening, tenor, tanggal presentasi, instruksi perpanjangan/pengembalian | tanggal presentasi ≥ jatuh tempo; reminder H-3 otomatis; pembatalan butuh otorisasi 2 orang | In Safekeeping |
| Rekon-Fisik Warkat | M1/M6 | temuan (Destroyed / Recovered / Misplaced), berita acara, saksi, nomor dokumen | wajib 2 otorisasi + lampiran; Destroyed tidak bisa dibatalkan (hanya dicatat sebagai kejadian baru) | status akhir + tautan berita acara |
| Batch Dispatch Pembayaran | M4 | kanal (LLG/RTGS/SKNBI/giro internal), file input, total & jumlah item, rekening sumber | kontrol total baris vs nominal (satu baris salah = batch ditolak); limit & velocity guard; ack ≤ 3 s per 5.000 item | Submitted → Acked/Rejected per item |
| Pembalikan (Reversal) | M4 | referensi transaksi asal, alasan, nominal parsial/utuh | tidak mengedit baris asal; jurnal compensating; otorisasi terpisah dari pembuat asal | transaksi baru bertaut |
| Impor Mutasi Bank | M5 | format (CSV/MT940/camt.053/API), periode, rekening, file | schema validation per format; baris gagal → file pengecualian, bukan batch gagal total | Staged siap cocok |
| Pencocokan Rekonsiliasi | M5 | kandidat pasangan, tingkat keyakinan, alasan manual, action (cocok/tolak/tahan) | pencocokan di bawah ambang butuh alasan teks ≥ 10 karakter; semua keputusan tercatat + siapa | Matched/Exception |
| Antrean Pengecualian | M5 | pemilik, prioritas, SLA, tindakan, catatan | tanpa pemilik = tidak boleh disimpan; eskalasi otomatis > SLA | Open → Resolved |
| Penutupan Periode (Close) | M5 | periode, saldo, tanda tangan internal, lampiran | toleransi harus 0 sisa ATAU pengecualian terdaftarkan; close tidak bisa mengulang periode terkunci | Closed (periode terkunci) |
| Master Nasabah / Rekening | M7 | identitas, NPWP, rekening, penanda PII, alamat, kontak | kolom PII wajib terdaftar di katalog (sec.pii_field) — kalau tidak, ALTER ditolak | aktif / tahan |
| Produk, Arrangement & Aturan Biaya | M7 | kode produk, struktur biaya, preferential pricing, toleransi per produk | perubahan tarif = parameter → dual control; berlaku efektif tertanggal (tidak surut) | draf → terjadual → aktif |
| Day-Zero Loader | M7 | file referensi massal, pemetaan kolom, mode (uji/serius) | laporan entitas yatim harus kosong sebelum import sah; idempoten per batch | selesai + ringkasan |
| Parameter Sistem | M6 | nama, nilai, rentang, dampak (restart?), alasan | apply_parameter() menolak sebelum ada approval; nilai di luar rentang ditolak di DB | pending → applied |
| Break-Glass & Tinjauan 24 Jam | M6/M9 | tiket, durasi, alasan, pencatatan pasca-akses | kedaluwarsa otomatis; akses tetap tercatat di rantai; tinjauan ≤ 24 jam wajib diisi | aktif → ditutup + ditinjau |
Coba satu: form Penerimaan Warkat (demo di browser, tidak ada jaringan)
Validasi di bawah ini adalah logika yang sama yang dijalankan klien — dan yang ditegakkan ulang di database. Isi asal-asalan untuk melihat mana yang ditolak.
Cash management enterprise
Diadu dengan aplikasi cash management yang dipakai korporasi di Indonesia
Yang di sebelah kanan bukan pesaing yang sama bentuknya: Mandiri MCM, BCA myBCA Bisnis, BRI Cash Management + QLola, BNI BNIDirect, CIMB BizChannel adalah kanal bank — mereka boleh men-debit rekening, kita tidak. Kyriba dan Nomentia adalah lapisan treasury multibank. Orivo ada di lapis operasional warkat + rekonsiliasi + kontrol yang ditegakkan database. Empat tabel di bawah mengadu empat hal yang benar-benar ditanyakan pembeli: fitur, modul, menu, form — lalu keputusan yang keluar dari perbandingan itu.
Dibaca dari materi publik 2026-09-03 (halaman produk, RIPLAY/buku panduan bank, listing pasar TMS). Tidak diuji hands-on, tidak ada klaim harga atau SLA.
Fitur — 22 hal yang diminta dari cash management enterprise
| Fitur | Orivo | Kanal bank (Mandiri · BCA · BRI · BNI · CIMB) | TMS (Kyriba · Nomentia · lainnya) | Catatan / tindak |
|---|---|---|---|---|
| Transfer antar rekening sendiri & antar bank (LLG/SKNBI/RTGS/BI‑FAST) | ◐batch & file keluar siap serah; debit dieksekusi bank | ✅inti setiap portalbmrn | ✅payment hub + cockpitko | by design — Orivo tidak memegang akses debit; jalur eksekusi = adapter (M17) |
| Unggah file pembayaran massal + pilih mode otorisasi: per file ATAU per baris | ✅dua lapis: DB menegakkan pay.batch.auth_mode = file|line (dibekukan setelah submit) + wf.chk_line_authorization; aplikasi menegakkannya di ecm-app/backend/controls.py (set_auth_mode, authorise_line) dengan pemilih mode & otorisasi per baris di menu Kontrol Gap CMS; /book menolak selama ada baris menunggu — 4 penolakan diuji di tests/smoke.py (165/165) | ✅BCA: bulk authorization vs individual authorizationb | ✅aturan rilis per level | → H‑17 ditutup di dua lapis (DB 008/009 + aplikasi controls.py); yang belum: berkas format bank (pain.001/MT103) sebagai kanal masuk — M14 |
| Cetak & kirim advis/bukti transfer ke penerima | ◐antrean advis di DB: adv.advice + adv.claim()/finish() (FOR UPDATE SKIP LOCKED, backoff 2^n menit, setelah gap.advice_max_attempts antrean berhenti dan tampil sebagai GAP), isi beku sejak Queued — di aplikasi: adv_templates (sahkan 4‑eyes sebelum dipakai) + adv_items dengan claim → sent/failed, bukti kirim wajib, dan dua trigger anti‑hapus/anti‑ubah (adv_no_delete_evidence, adv_no_edit_sent); yang belum: render PDF & kanal kirim nyata (SMTP/faks); kanal keluar sudah jalan di aplikasi: adv_deliveries append-only + penyedia local-outbox (berkas .eml di data/outbox/) atau SMTP bila app_settings.smtp_host terisi, render HTML + sidik jari sha256, baris Sent tidak bisa dirender maupun dikirim ulang; yang belum: PDF dan e-meterai | ✅Mandiri Advice Printingm · BCA Remittance Adviceb | ◐umumnya lewat email bank | → M14 / H‑18: antrean + bukti sudah ditegakkan dua lapis; penyematan dokumen (PDF, e‑meterai H‑16) masih terbuka |
| Pembayaran pajak massal (single/bulk) + unduh BPN/SSP | ✗ | ✅Mandiri bayar pajak via file upload, unduh BPN & SSPm · BNI POPSn | ✗di ERP/sistem pajak | by design (ADR‑14): siklus & nomor seri pajak tetap di sistem pajak |
| Auto‑debit & mandat penagihan (collection mandate) | ✅kontrak mandat di DB: coll.mandate + coll.check_debit — hanya status 'active', dalam jendela berlaku, ≤ amount_max, plafon periode kumulatif, satu debit per periode sesuai frequency, sumber pdf/counter wajib evidence_key — di aplikasi: mandates (period_cap/source) + coll_debits + controls.mandate_check, dengan form pengajuan dan otorisasi approver kedua di UI; nominal yang sudah diajukan tidak bisa diedit (jejak audit tetap utuh); yang belum: penangkapan persetujuan nasabah (e‑signature/dokumen mandat); di aplikasi controls.mandate_attest/mandate_revoke mencatat persetujuan nasabah (rujukan + nama + sidik jari berkas) dan request_debit menolak 409 tanpa itu; masa pembatalan revoke_window_days menahan debit sampai lewat; layar mandat + modal pencatatan ada | ✅BCA Collection Mandateb · Mandiri Auto Debit (Receivable)m · BNI Autodebetn | ✗ | → H‑19 ditutup dua lapis untuk penegakannya; formulir persetujuan nasabah = M14 |
| Virtual account untuk mengidentifikasi penyetor | ✅nomor VA & pencocokan penerimaan di DB: coll.virtual_account (aktif/tidak aktif, kedaluwarsa, plafon) + coll.va_match() — exact 100 vs suffix8 80; va_number terdaftar di katalog PII dan keluar sebagai ****0101 — di aplikasi: virtual_accounts + controls.va_match (plafon, tanggal kedaluwarsa, dan validasi data induk: VA yang menunjuk nasabah tak dikenal/tak aktif tidak pernah di‑credit) dengan masking dikerjakan di SQL sehingga list API, GET per‑record dan export CSV sama‑sama termasking; yang belum: penerbitan nomor oleh bank (by design) & pencocokan massal terhadap berkas penerimaan; di aplikasi: impor massal berkas penerimaan (controls.va_match_bulk) meng-credit otomatis dan idempoten; baris tak dikenal, duplikat, atau melebihi plafon ditahan; layar menerima CSV tempelan | ✅BNI e‑Collection / VA + portaln · Mandiri Bill Collectioni | ✅penerimaan via bank rails | → M14: QRIS/VA sebagai opsi pelunasan; pencocokan massal masuk fase berikutnya |
| Likuiditas: cash pooling, cash distribution, range balance, account sweep (AFT/AGF) | ✅lapis aturan & posisi di DB: liq.snapshot (append‑only, stamp masa depan ditolak), liq.rule_import (range balance wajib min & max; rentang periode tidak boleh tumpang tindih), liq.sweep_record (rekening sama ditolak, bank_ref unik), liq.v_position + is_fresh dari gap.liq_freshness_minutes — yang menjalankan sweep di bank tidak ada; di aplikasi: liq_sweep_rules (min/maks/arah/prioritas + jadwal cash_pools.sweep_time) dan controls.sweep_plan/sweep_execute — hanya aturan Active yang dipakai, eksekusi di luar jadwal wajib force_reason, nominal dinilai check_limit, butuh approver kedua | ✅Mandiri 3 fitur (pooling/distribution/range balance)m · BRI AFT/Sweep/AGFr · BNI liquidity mgmtn | ✅notional pooling, in‑house banking, netting multilateralkt | ADR‑15 DITETAPKAN 2026‑09‑03 → Opsi A; yang dibangun baru lapis aturannya (lihat tabel keputusan) |
| Penempatan & perpanjangan deposito online + pantau tenor | ✗ | ✅CIMB time deposit placement di ponselc · BRI Time Deposit Monitoringr · Mandiri (tipe rekening Deposito)m | ✅modul investment | by design: produk simpanan milik bank |
| Buka rekening giro/deposito online (real‑time) | ✗ | ✅BNI Online Open Accountn | ✗ | by design: KYC & dokumen legal bukan domain ECM |
| Trade finance: LC impor/ekspor, SKBDN, bank guarantee | ✗ | ✅BRI QLola Cash and Trade (CMS + trade + bank guarantee)r · BNI Trade (dokumen LC)n | ✅myDiapason punya modul Guarantees; Tijori: loans/LC/BG + covenantt | yang kita catat: warkat & dokumen penjaminan yang masuk siklus penagihan (kolom referensi, fase 4) |
| Query saldo & mutasi real‑time lintas bank (host‑to‑host) | ✗jalur kita = impor berkas, dan itu ditulis apa adanya | ✅setiap kanal bank | ✅9.900+ bank (Kyriba)k · 10.000+ bank (Nomentia)o | H2H = M17 dengan uji kontrak; tanpa itu kita tidak mengklaim visibilitas real‑time |
| Rekening koran & riwayat panjang + unduh MT940/PDF | ✅partisi bulanan + ensure_partitions/archive_partitions; pruning diuji (002) | ✅Mandiri MT940 & balance history 12 bulanm · BRI riwayat s.d. 5 tahunr | ✅inbound statement otomatis | yang belum: parser MT940/camt + golden file (H‑4) |
| Rekonsiliasi bank + toleransi + antrean pengecualian | ✅recon.{file,statement_row,break} + toleransi per produk di ref.tolerance — 10/10 di 007 | ◐umumnya dikerjakan di sisi nasabah/ERP | ✅GL reconciliation + cash accountingk | keunggulan kita: toleransi ditegakkan database, bukan di layar |
| Peramalan kas & skenario (termasuk yang pakai AI) | ◐heuristik lokal berbobot + adapter LLM opsional; tanpa jaringan tetap jalan | ✗bukan fitur portal bank | ✅AI cash forecasting, skenario bergulirkt | kita tidak menjanjikan AI; kita menjanjikan angka yang bisa dihitung ulang |
| Taksonomi limit: per perusahaan · per rekening · per transaksi releaser · per level workflow · otorisasi langsung · per hari collection | ✅taksonomi limit di DB: wf.limit_policy (scope company|account|releaser|step, per_txn_max + daily_max, masa berlaku, satu kebijakan aktif per (scope, kunci) via EXCLUDE, diubah 4‑eyes) — dinilai wf.chk_task_limit saat langkah Done; di aplikasi: wf_limits + controls.check_limit menutup keenam jenis limit (perusahaan, rekening, releaser per transaksi, step = tiering, Direct Authorization Limit, plafon harian kolaborasi penagihan), pemakaian harian dihitung DARI data, dan 14 pemeriksaan limit, 9 di antaranya penolakan 409/403 | ✅BCA mendata 6 jenis limit, publikb | ✅rule-based payment controlso | → H‑17 ditutup dua lapis; layar kebijakan limit (form + sahkan 4‑eyes) sudah ada di Kontrol Gap CMS → Limit & 4‑eyes. Padanan “Limit Workflow (tiering)” adalah skop step — istilah vendor, pemetaan milik kami |
| Hak akses & skema persetujuan: maker · checker · releaser · signer, dual control admin, akses per menu | ✅wf.chk_sod, sec.chk_no_self_grant, ops.apply_parameter 4‑eyes — di database | ✅Mandiri sysadmin1/sysadmin2 dual controlm · BNI maker‑checker‑signern | ✅ Approval workflow + segregation of duties | beda kita: tiap jalur bypass punya uji (S.8/S.9/S.20), bukan kebijakan manual |
| Device binding + token (hard/soft, M‑PIN+OTP, biometrik) | ◐tabel sec.device_binding + MFA peran autorisasi, tapi belum di filter login (G5) | ✅CIMB: 1 user = 1 perangkat aktifc · BNI M‑PIN+OTP untuk menu sensitifn · KeyBCAb | ✅SSO + device policy | G5 tercatat di #keamanan, tidak dihaluskan |
| Persetujuan dari aplikasi ponsel + push ke antrean | ✗HTML5 responsif saja; tanpa aplikasi toko | ✅BizChannel@CIMB Mobile: approve pending task (payroll, bulk)c | ◐tergantung produk | → M14 / H‑9 |
| Sanction screening & deteksi fraud pembayaran | ◐gerbang di DB: trigger pada pay.item menolak rilis tanpa hasil skr dalam gap.screening_max_age_minutes (1440), result='error' = TAHAN (bukan lolos), hit tanpa baris scr.hit = ditolak, hit hanya bisa dilepas override 4‑eyes — di aplikasi: scr_lists/scr_entries/scr_runs/scr_overrides + controls.verdict dipanggil sebelum langkah workflow ditandai Done dan lagi oleh /book; daftar lokal, pemetaan nama/rekening (exact vs fuzzy→indeterminate), override butuh alasan ≥12 karakter + approver kedua dan bisa dibatasi nominal; yang belum: penyedia daftar nyata (adapter M17) — hasil eksternal masuk lewat result= dan sudah diuji; di aplikasi: registri penyedia daftar (scr_providers) + scr_sync_log bernomor versi — sinkron 0 baris ditolak, penyedia gagal membuat daftar lama tetap berlaku, aktivasi penyedia butuh approver kedua | ◐dijalankan bank, tidak terlihat di layar nasabah | ✅Nomentia: automated sanctions screeningo · Kyriba: fraud preventionk | → H‑21 ditutup dua lapis untuk gerbangnya; penyedia daftar (World‑Check/Dow Jones/Refinitiv) = adapter M17 dengan uji kontrak |
| Analisis biaya bank (fee analysis vs tarif) | ◐ref.charge_rule (tarif + preferential pricing) ada; pencocokan invoice biaya bank belum | ✗ | ✅Nomentia: bank fee analysiso | murah: satu aturan pencocokan di M5 — tidak perlu modul baru |
| Portal pihak ketiga / ekosistem billing | ✗ | ✅BNI ECOSmart + VA Portaln · Mandiri Billi | ◐di AR/AP suite | by design: ini kanal bank, bukan tempat warkat |
| Multi-entitas, konsolidasi grup, in-house banking, netting | ✗ | ◐struktur rekening bertingkat per organization unit sajam | ✅inti penawaran TMSkt | by design (ADR‑14 + ADR‑15) — entitas & saldo tetap punya satu pemilik |
Modul — bagaimana tiap produk menata modulnya
| Produk | Modul/layanan yang diakui publik | Bentuk / pola jual | Padanan di Orivo |
|---|---|---|---|
| Mandiri — MCM 2.0 / Kopra Cash Managementm | Dashboard kustom · Account (list, today’s balance, balance history 12 bln, statement cetak/MT940, report overview) · Advice Printing · Transfer · Payment (pajak, biller) · Receivable (auto debit) · Liquidity (pooling, distribution, range balance) · Budget Account · Transaction Status · admin user (sysadmin1/sysadmin2) | layanan bank, bukan lisensi modul | parsial: M4 dispatch · M6 otorisasi (limit 4 skop + otorisasi per baris sejak 008) · M7 referensi; sisanya kanal bank |
| BCA — myBCA Bisnis / KlikBCA Bisnisb | Bulk Transfer (unggah file, pilih bulk/individual authorization) · Remittance Advice · Collection + Collection Mandate · 6 jenis limit · informasi rekening | portal + KeyBCA/token | M4 + M6; otorisasi per baris masuk H‑17 |
| BRI — Cash Management System + QLolar | Financial dashboard (saldo real-time, riwayat, mutasi) · Account Information (statement s.d. 5 tahun, summary, time deposit monitoring) · Funds Transfer · AFT/Account Sweep/AGF · Cash and Trade (CMS + trade finance + bank guarantee) · Supply Chain Management (invoicing) | portal bank + modul likuiditas | M5 kita lebih dalam (toleransi + pengecualian); siklus hidup warkat tidak ada di mereka |
| BNI — BNIDirectn | Inquiry · Transfer Mgmt (in-house, LLG/RTGS/IFT) · Mass Payment (payroll, bulk) · Liquidity Mgmt (pooling, distribution) · Tax/Billing/Utility Payment · Autodebet · Virtual Account Mgmt · Trade · Online Open Account · e-Report · menu & jumlah user menyesuaikan kebutuhan nasabah | web + mobile + API, dua bahasa | “menu yang bisa disusun” = portlet kita (M8); kanal keluar masih usulan (M14) |
| CIMB Niaga — BizChannel@CIMB (+ Mobile)c | Approve pending task dari ponsel (payroll, bulk) · saldo/mutasi/status real-time · overbooking, SKN, domestik online, remittance, bills, tax · time deposit placement · 1 user = 1 perangkat | portal + aplikasi toko | device binding ada di skema kita tapi belum di filter (G5) |
| Kyriba (TMS)k | cash & liquidity (pooling, in-house banking, netting) · payment hub + Payment Cockpit · risiko FX/IR/debt/investment · working capital order-to-cash · koneksi 9.900+ bank & 10.000 instance ERP · AI forecasting · fraud detection · SOC 1/2 Type II | SaaS multi-tenant; implementasi dilaporkan hingga 8 bulan | tumpang tindih nyata hanya di M5 + M7; sisanya by design |
| Nomentia (TMS)o | payment hub + kontrol berbasis aturan · pencegahan fraud · sanctions screening otomatis · koneksi bank + konversi format file (10.000+ bank, multi-protokol) · bank account management · bank fee analysis · cash forecasting · loan management | managed connectivity | fee analysis → satu aturan di M5; sanctions → adapter (M17), bukan modul |
| Pemain TMS lain yang dijual ke korporasi di Indonesiat | pola modul yang berulang: Liquidity · Payment · Risk · Invest · Guarantees (myDiapason 5 modul) · facility loans/LC/BG + covenant (Tijori) · netting & in-house banking (Coupa/Bellin, GTreasury) · forecasting murni (Cashforce) | enterprise suite, lisensi per modul/entitas | pola beli bertahap kita sama (M1–M10 + M11–M18); lapisnya beda — kita pegang warkat & bukti fisik |
| Orivo | M1 penerimaan warkat · M2 kliring & penagihan · M3 PDC/CDC · M4 dispatch pembayaran · M5 rekonsiliasi · M6 maker-checker & parameter · M7 referensi hari-nol · M8 portal & portlet · M9 audit rantai & forensik · M10 inteligensi lokal; usulan M11–M18 | satu PostgreSQL + 8 layanan; modul dipakai bertahap | — |
Menu — daun yang benar-benar ada di layar
| Kelompok menu | Daun khas kanal bank (contoh terdokumentasi) | Orivo (dihitung dari #menu) | Yang kami ambil / tidak |
|---|---|---|---|
| Beranda / dashboardmr | menu favorit, status transaksi, kalender, berita, cut-off; dashboard bisa dikustom | 4 daun · 🏠 Beranda / Portlet | kalender cut-off per bank masuk ke ref.calendar_day + parameter (fase 2) |
| Informasi rekeningmr | account list, today’s balance, balance history, statement (cetak/MT940), report overview, budget account | 3 daun · 📊 Laporan | kita tidak query bank: laporan dibangun dari mutasi yang diimpor; “budget account” tidak diambil (by design) |
| Siklus hidup warkat | tidak ada padanan — cek/bilyet giro masuk sebagai transaksi kliring, bukan dokumen dengan status | 6 daun · 🧾 Warkat | — (di sini kami tidak diadu) |
| Pembayaran / transferbn | single & bulk transfer, multi transfer, payroll, tax, biller, autodebet, status transaksi | 4 daun · 💸 Pembayaran | mode otorisasi per baris (H‑17) & advis (H‑18) kami ambil dari pola mereka — keduanya sudah ditegakkan di DB sejak 008 |
| Rekonsiliasi & tutup hari | unduh statement + report; rekonsiliasi biasanya di ERP/nasabah | 5 daun · 🔁 Rekonsiliasi | tidak ada yang diambil — kami yang lebih dalam (break, umur, toleransi, close) |
| Likuiditasmrn | cash pooling · cash distribution · range balance · AFT/Account Sweep/AGF · time deposit | ◐ view Likuiditas + tab Sweep | grup ini tidak ada di Orivo — diputuskan di ADR‑15 (adapter vs modul), bukan dilupakangrupnya sudah ada di aplikasi (pool, posisi, ramalan, sweep); yang belum = daun notional pooling di sisi bank |
| Referensi / struktur rekeningm | rekening terdaftar per tipe (giro, tabungan bisnis, pinjaman, deposito), organization unit, mata uang | 4 daun · 👥 Referensi | tipe rekening & flag “bisa di‑query” masuk sebagai kolom ref.account (fase 2) |
| Otorisasi & admin usermbn | sysadmin1/sysadmin2 (dual control), akses menu, limit, skema persetujuan, pending task | 4 daun · ⚙️ Admin sistem | “akses per menu” kita sudah punya (grant per tabel + peran); pending task per orang = portlet Antrean saya |
| Keamanan & jejakn | login audit, token management, laporan aktivitas, notifikasi email | 4 daun · 🛡 Keamanan | kita naikkan jadi rantai hash + verifier + alert; notifikasi = M14 |
| Kanal keluar: advis, bukti, tagihan | Advice Printing, Remittance Advice, e-Report, kirim via email terjadwal | ◐ antrean advis + jejak kirim | belum ada grupnya → M14 (H‑18); yang diambil: pola “laporan terjadwal + kirim surel”sudah ada di dalam Kontrol ▸ Advis (pratinjau + kirim + jejak append-only); grup menu tersendiri belum |
Form — yang harus diisi orang, baris per baris
| Form (dari materi publik) | Di produk | Status di Orivo | Tindak lanjut |
|---|---|---|---|
| Pendaftaran rekening ke portal (jenis: giro · tabungan bisnis · pinjaman · deposito)m | Mandiri KCM | ✗tidak ada | tetap di bank; yang kita impor: struktur & tipe rekening ke ref.account |
| Unggah file pembayaran massal + peta kolom + validasibn | BCA bulk transfer via file · BNI mass payment | ◐sebagian | form #8 Batch Dispatch Pembayaran sudah ada (peta kolom + idempoten per nomor batch) |
| Pilih mode otorisasi: seluruh file ATAU per barisb | BCA “bulk vs individual authorization” | ✅pemilih mode (file|line) + panel otorisasi per baris ada di Kontrol Gap CMS → Otorisasi per Baris; mode dibekukan saat submit dan penolakannya diuji | → H‑17 fase 3: kontrak DB-nya sudah ada & diuji (pay.batch.auth_mode, wf.chk_batch_auth_mode: “sebagian baris diotorisasi, sisanya tetap tertahan” ditolak) — yang kurang hanya formulirnya |
| Form collection mandate / persetujuan auto-debitbm | BCA · Mandiri Receivable | ✅form pengajuan auto‑debit (mandat, nominal, tanggal, sumber, bukti) + otorisasi approver kedua sudah ada; persetujuan nasabah (e‑signature) belum; persetujuan nasabah ikut dicatat (rujukan + sidik jari + masa pembatalan) dan ditegakkan saat debit diajukan | formulirnya belum; kontrak DB-nya sudah ditegakkan sejak 008 (coll.mandate, coll.check_debit) — sisa pekerjaannya cuma layar & jalur kirim ke bank |
| Form Virtual Account management (buat/ubah/limit/rekening tujuan)n | BNI VA + e-Collection portal | ✅CRUD VA + kotak pencocokan referensi + masking di list/record/ekspor tersedia; penerbitan nomor tetap di bank; pencocokan massal berkas penerimaan ada di layar yang sama (CSV tempel, hasil per kelas) | M14 (fase 4) |
| Form advis/notifikasi tertulis (pilih transaksi → cetak → kirim)mb | Mandiri Advice Printing · BCA Remittance Advice | ✅antrean advis per baris + claim/terkirim/gagal dengan bukti wajib tersedia di UI; cetak PDF & surel otomatis belum; pratinjau dokumen, kirim ke outbox/SMTP, dan jejak kirim append-only ada di UI — yang belum hanya PDF dan tanda tangan | → H‑18, fase 4 (di dalam M14): advis sebagai dokumen, bukan lampiran email opsional |
| Form pembayaran pajak single/bulk + unduh BPN/SSPmn | Mandiri · BNI POPS | ✗tidak ada | by design (ADR‑14) |
| Form aturan likuiditas (rekening sumber/sub, range balance min/maks, jadwal sweep)mr | Mandiri Liquidity · BRI AFT/Sweep/AGF | ✅layar aturan range balance per rekening (min/maks/arah/prioritas) + sahkan 4-eyes + jalankan sweep; posisi notional di bank tetap Opsi A (ADR-15) | ADR‑15: opsi A = impor aturan untuk dilaporkan; opsi B = modul kas internal — rekomendasi A |
| Form penempatan deposito (tenor, instruksi jatuh tempo)cr | CIMB mobile · BRI monitoring | ✗tidak ada | by design |
| Form user + akses menu + limit + skema persetujuan (dual control sysadmin)m | Mandiri sysadmin1/sysadmin2 | ✅ada | form #3 Otorisasi (Maker-Checker) + #17 Parameter Sistem + #18 Break-Glass — guard-nya di database |
| Form impor rekening koran/mutasi (periode → MT940/PDF)m | Mandiri statement download | ✅ada | form #10 Impor Mutasi Bank; parser MT940/camt = H‑4 |
| Form rekonsiliasi & “out of balance” | portal bank biasanya tidak punya; kita yang menutupnya | ✅ada | form #11 Pencocokan Rekonsiliasi + #12 Antrean Pengecualian; toleransi per produk baru saja diuji (007 R.6/R.7) |
| Form approve pending task di ponselc | BizChannel@CIMB Mobile | ✗tidak ada | M14/H‑9; web responsif + MFA dulu |
| Form registrasi perangkat + token/M-PINcn | CIMB 1 perangkat; BNI M-PIN untuk menu sensitif | ◐sebagian | skema sec.device_binding ada + diuji; penegakan di filter login = G5/H‑7 |
| Form laporan terjadwal (format + jadwal + surel)nm | BNI e-Report · Mandiri report overview | ◐sebagian | M18 (report studio read-only) — “kirim terjadwal” masuk fase 5 |
Empat keputusan yang keluar dari perbandingan ini
| Domain | Opsi A — adapter | Opsi B — modul penuh | Rekomendasi & syarat |
|---|---|---|---|
| Likuiditas: pooling, sweeping, range balance, in-house banking, netting | Opsi A — adapter. Impor aturan & hasil sweep (file/MT940), laporkan posisinya, jangan pegang mandat debit. ±12–18 dev-day, 3 tabel. | Opsi B — modul penuh. liq.policy/liq.sweep_run/liq.ledger + jadwal + netting + in-house bank. ±150–220 dev-day, ±20 tabel, dan menabrak satu pemilik saldo. | Opsi A — DITETAPKAN 2026‑09‑03. Lapis aturannya dibangun di DB (liq.snapshot, liq.rule_import, liq.sweep_record, liq.v_position), bukan modul penuh. Satu syarat tetap berlaku: posisi kas harian harus tetap terbaca di #laporan tanpa akses debit. Kalau bank tidak menyediakan file sweep, fitur itu memang tidak bisa dijanjikan. |
| Sanction screening & fraud detection | Opsi A — adapter ke penyedia daftar (M17) dengan uji kontrak + status “tidak checked = tahan”. | Opsi B — modul AML: daftar, fuzzy match, kasus, SLA audit. Beban regulasi + lisensi data. | Opsi A — dan guard itu bukan wacana lagi: scr.verdict() menolak rilis tanpa hasil skr, error = TAHAN, hit butuh scr.override 4‑eyes (diuji di 009). Yang jadi milik kita tetap: menahan item yang belum terbebas, bukan menjadi AML. |
| Bank fee analysis | Opsi A — aturan di M5: tagihan biaya bank vs ref.charge_rule, selisih masuk antrean pengecualian. | Opsi B — modul biaya: kontrak tarif per bank, negosiasi, recovery ke nasabah. ±40 dev-day. | Opsi A. B hanya kalau tarif bank jadi barang yang dijual ulang, dan itu keputusan bisnis, bukan teknis. |
| Aplikasi ponsel untuk otorisasi | Opsi A — web PWA + push (M14): antrean, badge, otorisasi dengan MFA; tanpa aplikasi toko. | Opsi B — aplikasi native dua toko + review + signing + force-update. ±50 dev-day/tahun perawatan. | A sekarang; B ditinjau kalau SLA otorisasi luar jam kerja benar-benar jebol (H‑9 mengukur itu). |
wf.chk_sod, sec.chk_no_self_grant dan guard parameter hidup di database, dan tiap upaya bypass punya uji (S.8/S.9/S.20) — bukan kebijakan yang bisa dilanggar di layar.Keamanan & kepatuhan
Dipetakan ke kerangka regulator — tapi yang dijual di sini adalah penolakannya
Kisi-kisi kepatuhan itu syarat administratif. Yang kami tawarkan adalah kondisi sistem: apa yang ditolak, di lapisan mana, dan dengan uji nomor berapa.
Ditegakkan di lapisan data (bukan di UI)
- 4 peran DB + RLS jalur portal;
ecm_readonlyditolak saat menyentuhbeneficiary_account,local_hash,jti - Audit
UPDATE/DELETE→ ditolak pemicu; pemalsuan hash hanya terbaca oleh verifier rantai (itu yang membuatnya berguna) - Parameter/limit/toleransi:
apply_parameter()menolak sebelum ada approval; perubahan tidak surut - Katalog PII wajib: kolom PII tanpa registrasi →
ALTER TABLEditolak dengan pesan yang menunjuksec.pii_register() - Masking di DB dan di log; uji Logback nyata membuktikan pola
****7890keluar dari appender - Break-glass berkedaluwarsa, wajib tiket, tetap tercatat;
pgAuditpadaddl,role(bukanread— yang membanjiri log dan menutupi yang penting) - hba:
scram-sha-256+hostssl; koneksi TCP non-TLS ditolak (uji negatif di skrip setup) - Arsip WAL = pengikat RPO, dibaca
pg_stat_archiver→ kontrol hidup + alert
Ditegakkan di lapisan aplikasi & antarmuka
- Keycloak OIDC Authorization Code + PKCE; sesi via cookie (
HttpOnly/SameSite/Secure) — bukan token dilocalStorage - Validasi token dengan
DelegatingOAuth2TokenValidator;jtireplay ditolak (uji) - Guard velocity fail-closed: backend mati = transaksi ditahan, bukan diloloskan
- CSP + nonce per respons,
Trusted Types, tanpainnerHTMLuntuk data pengguna (ArchUnit + uji filter) - Semua tulis idempoten (kunci bisnis), retry aman; ack per item, bukan hanya per batch
- Timeout eksplisit di jalur DB/Hikari/Kafka/adapter LLM; tidak ada panggilan tak berbatas
- Graceful shutdown + preStop; rollout tidak memutus saga di tengah commit (target; lihat gap G5/G11)
| Rujukan | Yang Orivo jadikan kewajiban teknis | Status di repo |
|---|---|---|
| POJK 11/POJK.03/2022 (penyelenggaraan TI & ketahanan siber) | arsitektur terdokumentasi, siklus aset→ancaman→perlindungan→deteksi→pemulihan, MIS ketahanan siber, pentest berkala | ✅ deteksi/pemulihan terbukti (21 alert, drill PITR) · 📄 pentest = administratif |
| SEOJK 29/SEOJK.03/2022 | perimeter deny-by-default, OTP untuk transaksi berisiko, basis data baca-saja untuk non-DBA, MFA untuk data sensitif, tanpa workstation↔workstation, kanal terenkripsi | ✅ peran baca-saja + MFA + TLS diuji · ◐ OTP perangkat (G5) |
| SWIFT Customer Security Programme v2026 (32 kontrol: 26 wajib + 6 advisory) | Secure environment, know & limit access (tinjauan akses kuartalan), detect & respond (logging terpusat + tinjauan harian, retensi ≥ 3 tahun, IR plan diuji ≤ 12 bulan) | ✅ rantai audit + retensi + break-glass · ◐ 2.6 session recording, 6.5 transaction analytics (G6) |
| PCI DSS v4.0.1 (51 requirement future-dated wajib sejak 31 Mar 2025) | perlindungan data penyimpanan, 6.4.3 skrip pembayaran di halaman, 11.6.1 deteksi perubahan tamper pada halaman pembayaran | ◐ SPA HTML5: CSP/nonce/Trusted Types ada; pembuktian 6.4.3/11.6.1 butuh CDN & tooling pihak ketiga (G11) |
| OWASP ASVS 5.0.0 | Level 2 untuk seluruh aplikasi, Level 3 di jalur rilis; V16 = log yang dapat dibuktikan & dapat dikaitkan ke orang | ✅ V16 dipenuhi row_hash + uji; pemetaan chapter per kontrol ada di dokumen |
| UU PDP 27/2022 + PP 71/2019 | data strategis diproses & disimpan di Indonesia; hak akses/hapus subjek data | ✅ on-prem, DB/cadangan di dalam negeri · ◐ katalog PII + masking; report/erase masih gap (G7) |
| PBI 10/2025 (TIKMI untuk penyelenggara sistem pembayaran) | manajemen risiko berbasis prinsip, pendaftaran vendor, perjanjian yang mencakup keamanan/BCP-DR, persetujuan sebelum berbagi data | ✅ BCP/DR teruji (drill) · 📄 pendaftaran vendor & perjanjian = administratif |
text ·
G5 device-binding belum di filter rantai · G6 SWIFT 2.6 (session recording) & 6.5 (transaction analytics) ·
G7 hak subjek UU PDP (report/erase) belum jadi primitif · G11 /actuator/prometheus + SBOM/cosign di CI ·
G12 Helm chart belum pernah di-apply ke klaster nyata.
Nama gap, pemilik, dan cara menutupnya ada di architecture/keamanan-perbankan.md §9 — dan halaman ini tidak menyebut "aman" tanpa daftar itu.Bukti & kapasitas
Angka yang bisa kamu jalankan ulang hari ini
Semua baris di bawah adalah keluaran perintah: lapis DB/Java terakhir diverifikasi 2026-09-03 pada gerbang ecm_gate6 (exit 0), lapis aplikasi diulang 2× beruntun pada 2026-09-04 (175/175 smoke, 69/69 probe, 48/48 harness jsdom, 14/14 migrasi). Yang tidak terukur, ditulis di kolom kanan sebagai "belum diukur".
| Yang diukur | Angka |
|---|---|
| Dasar desain: burst 95 %/30 menit | 528 TPS (rata-rata harian 11,6 TPS) |
Tulis massal pay.item (1 koneksi, fsync on) | 145–200 rb baris/dtk terukur — vs 2.111 baris/dtk yang dibutuhkan desain; kepalanya ~68×, tapi di satu mesin 2 vCPU |
Tulis dengan guard akuntansi (gl.entry) | 8,8–9,6 rb baris/dtk |
| Biaya masking PII per baris | median +6,3 ms (rentang −0,9…+16,1 ms = noise; bukan angka yang dipublikasikan sebagai "range") |
Agregasi SUM 200 rb baris | 26–33 ms → materialized view wajib, bukan opsional |
| Jejak penyimpanan 200 rb transaksi | 110 MB · 575,4 B/baris → 4,2 TB untuk 5 tahun |
| Kebutuhan koneksi (Hukum Little) | 21 koneksi aktif → 3 POD (HPA 3→12) |
| Perbandingan cash management enterprise (#cms) | 22 fitur (8 ✅ · 6 ◐ · 8 ✗ pada kolom Orivo) · 9 produk · 15 form (8 ✅ · 3 ◐ · 4 ✗) · 10 kelompok menu — dihitung dari markup halaman ini oleh harness (branding/test-halaman.mjs); sisi pesaing dibaca dari materi publik, bukan diuji hands-on |
| Referensi hari-nol (006 + 007): kalender, tarif 4-eyes, gerbang yatim, katalog PII | 10/10 lulus di klaster terkeraskan — dan ref.is_workday() menolak menjawab untuk kalender tahun yang belum dimuat (tidak ada tebakan senyap soal hari kerja) |
| Drill PITR: base backup | 13 MB (DB 95 MB), restore siap dalam 1 s, titik recovery tepat (200/200 di sebelum target, 0 di titik target) |
| Drill PITR: rantai audit & replika | rantai patah 0 → 0; replika melayani 1.850 baris audit saat primary mati |
| Kegagalan yang ditemukan sendiri | arsip WAL macet 75× tanpa satu pun gerbang protes → kini jadi kontrol + alert |
Belum diukur (dan itu bagian dari tawarannya)
- Kontensi multi-POD pada satu PostgreSQL (uji ini memakai 1 koneksi)
- Latensi aplikasi ↔ DB nyata (network hop), hanya waktu eksekusi di sisi server
- Bloat indeks/table setelah 12 bulan volume penuh
docker compose upend-to-end sebagai satu kesatuan- Hasil k6 terhadap klaster Kubernetes (skrip & ambang ada, belum dijalankan)
/actuator/prometheusdibuktikan lewat HTTP (G11)- Helm chart di-apply ke klaster nyata (G12)
- RTO 1 s dari drill = mekanisme, bukan RTO produksi; tidak ada host/situs kedua, pgBackrest/Barman, atau Object Lock
Reproduksi di mesin bersih
Perintah yang sama dipakai CI internal kami — bukan "hubungi sales untuk benchmark".
sudo apt-get install -y postgresql-17 postgresql-17-pgaudit \
openjdk-21-jdk-headless python3-yaml
deploy/setup-validation-cluster.sh --configure # 11 pemeriksaan + uji negatif TLS
deploy/dr-pitr-test.sh # drill PITR, angka tercetak
./validate.sh # 15 gerbang: SQL (002/005/007/009), manifest, alert, topik, build
Perkiraan: ±2 menit tanpa GPU, tanpa cloud, tanpa lisensi. Kalau salah satu gerbang merah, keluarannya menyebut nama pemeriksaan yang hilang — termasuk kalau ada pemeriksaan yang hilang diam-diam (itu kelas bug yang pernah kami temukan, dan sekarang jadi gerbang).
Cara dibangun
Modular monolith + tulang punggung peristiwa — bukan microservice demi gaya
Yang dipecah lebih dulu hanya yang punya alasan: intake warkat (volume & pola kegagalan berbeda), dispatch pembayaran (kanal eksternal), rekonsiliasi (batch berat). Sisanya tetap satu proses — dengan batas modul yang diuji ArchUnit.
Tumpukan
| Keputusan | Alasan yang bisa diuji |
|---|---|
| Valkey, bukan Redis | fork BSD-3-Clause dari Redis 7.2.4; kompatibel RESP2/RESP3 → Lettuce/Spring Data tidak berubah; ~20 % lebih hemat memori di YCSB; bukan jualan "Redis proprietary" |
| Satu PostgreSQL, bukan shard | 4,2 TB/5 tahun itu masalah retensi & partisi, bukan TPS; 2.111 baris/dtk di mesin 2 vCPU meninggalkan kepala yang besar |
| Kontrol di DB | UI bisa di-bypass, API tidak bisa di-bypass; kalau penolakannya tidak ada di DB, ia tidak ada |
| Audit berantai hash | ASVS V16 + SWIFT "central logging": yang menarik bukan "ada log", tapi "bisa dibuktikan tidak ada yang hilang" |
| Arsip WAL sebagai kontrol | RPO tanpa arsip yang dipantau = angka di slide. Kami punya buktinya (75 kegagalan yang tidak terlihat) |
Rencana
Enam fase, 9–12 bulan, tiap fase punya gerbang keluarnya sendiri
Fondasi & warkat dasar
Skema + kontrol di DB, intake/verifikasi/otorisasi, portlet antrean. Gerbang: 002, 005 & 007 hijau di klaster terkeraskan.
Kliring, retur, PDC/CDC
Impor berkas kliring, mesin retur, brankas titipan + reminder. Gerbang: rekonsiliasi 1,8 jt baris < 45 menit di ukuran produksi (target desain, belum diukur di klaster).
Dispatch & kanal
Batch 5.000 item/ack ≤ 3 s, adapter bank (SKNBI/RTGS/LLG), reversal. Gerbang: idempotensi diuji ulang + DLT.
ISO 20022 & arus kas
camt/pacs, prediksi arus kas dari tenor warkat, aging & kolektibilitas. Gerbang: uji kontrak format per bank.
Intelijen lokal
Skor pengecualian, saran pasangan, adapter LLM opsional (fail-open). Gerbang: fitur inti tetap hijau saat adapter dimatikan.
Go-live & penutupan gap
KMS/HSM, SBOM/cosign di CI, device-binding di filter, hak subjek UU PDP, chart di klaster nyata. Gerbang: daftar §9 kosong atau ber-pemilik + bertanggal.
Pertanyaan yang biasanya muncul di rapat
Enam jawaban, tanpa kata "solutif"
Kenapa tidak ada saldo real-time atau cash pooling seperti di MCM/BNIDirect?
Karena keduanya menuntut hak men-debit rekening bank, dan itu tidak kami pegang. Yang kami pegang: siklus warkat, berkas pembayaran keluar, rekonsiliasi, dan otorisasi yang ditegakkan database. Kalau bank memberi file posisi/mutasi (MT940/camt), angkanya masuk ke laporan kami; sisanya tercatat di register — M17 (katalog koneksi bank) dan ADR‑15 (likuiditas sebagai adapter, bukan modul). Daftar lengkapnya ada di #cms, termasuk yang kami kalah.
Kenapa kontrolnya di database? Bukankah itu membuat DB berat?
Karena hanya di sana penolakan berlaku untuk semua jalur (UI, API, script, integrator). Biayanya kami ukur: guard akuntansi 8,8–9,6 rb baris/dtk pada satu koneksi di mesin 2 vCPU. Yang mahal bukan kontrolnya, melainkan materialisasi agregat (yang juga sudah kami ukur).
Apakah AI/LLM wajib online?
Tidak. Yang wajib jalan adalah statistik lokal (prioritas pengecualian, saran pasangan). Adapter LLM hanya menambah ringkasan/draft memo; ia boleh mati, timeout, atau dihapus tanpa fitur inti berkurang. Timeout & batas byte respons dipasang sejak awal. Bobot pencocokan lokalnya tercetak di ecm-app/backend/ml_engine.py — 55 untuk nomor referensi identik, 40 kunci pasangan terdaftar, 35 nominal persis, 26 selisih di dalam toleransi — dan tidak satu pun dari itu memanggil jaringan.
Bagaimana dengan data pribadi dan UU PDP?
Katalog PII itu wajib: kolom berisi data pribadi yang tidak terdaftar membuat ALTER TABLE ditolak. Masking berlaku di basis data dan di log, dan ekspor untuk peran auditor menghasilkan ****7890. Yang belum kami buat: primitif laporan & penghapusan atas permintaan subjek (gap G7) — kami tulis sebagai gap, bukan kami klaim.
Apa artinya "1 juta transaksi/hari" di sistem ini?
Rata-rata 11,6 TPS, puncak 95 % dalam 1 jam 264 TPS, dan dasar desain kami adalah burst 95 %/30 menit 528 TPS. Pertumbuhan ke 5 juta/hari masih 1 PostgreSQL dengan partisi (11,28 TB/5 th, 11 POD) — jadi yang menentukan adalah retensi & strategi partisi, bukan "harus microservice".
Berapa lama implementasi dan siapa yang mengerjakan?
Fase 1–3 (inti warkat + dispatch) 3–5 bulan dengan tim 4–6 orang bank + kami untuk adaptasi kanal. Yang biasanya paling lama bukan kodenya, melainkan day-zero reference data & kesepakatan format berkas dengan unit lain — karena itu modul M7 punya loader + laporan entitas yatim, bukan sekadar "import CSV".
Langkah berikutnya
Ajukan demo 30 menit — atau lewati kami dan jalankan sendiri gerbangnya
Kalau kamu tim arsitektur/IT bank: bentuk isian di bawah tidak mengirim ke mana-mana (halaman ini lokal). Di pemakaian nyata, isian ini masuk ke antrean presales lewat kanal internal bank.