Lewati ke konten utama
№ 04 / Blog 20 Oktober 2026

Platform Operasional Sendiri: dari Brankas ke SPT Coretax

Fajrian Aidil Pratama 12 menit baca

Platform Operasional Sendiri: dari Brankas ke SPT Coretax

Banua Coder, perusahaan perangkat lunak kecil di Palu, menjalankan rilis, rahasia, kontrak, tanda tangan, dan pajak dengan satu cara kerja yang kami bangun sendiri. Kami merilis aplikasi keuangan seluler, starter kit Flutter, layanan telemetri, API publik, pelacak bus, dan situs web kami sendiri. Tim sekecil kami hanya bisa menjaga semua itu tetap berjalan bila caranya seragam.

Kami mulai dari cara setiap produk dirilis, lalu masuk ke lima bagian: brankas rahasia untuk orang dan agen AI, platform operasional yang menjalankan perusahaan, dokumen bertanda tangan yang bisa diverifikasi siapa saja, panduan mengisi SPT Tahunan di Coretax, dan apa yang dilihat klien saat kami bekerja.

Diagram jalur rilis Banua Coder, dari rencana sampai pemantauan

Satu jalur rilis untuk setiap produk

Setiap repositori mengikuti enam tahap yang sama. Alatnya berbeda menurut stack, tetapi jalurnya tidak.

Rencana

Pekerjaan dimulai sebagai tugas di Beads, pelacak isu kami, atau sebagai isu GitHub. Catatan tim tersimpan di Obsidian. Agen AI membantu, dan aturannya spesifikasi lebih dulu: spesifikasi singkat ditulis sebelum kode.

Bangun

Pekerjaan dilakukan di branch fitur dan masuk ke develop lewat pull request. Pemeriksaan otomatis datang dari repositori workflow GitHub Actions milik kami yang dipakai ulang di semua repositori dan dikunci ke satu tag versi. Ada satu workflow untuk setiap stack: Go, Flutter, Laravel, Node, dan Rust.

Rilis

Kami memakai Git Flow. Branch release/x.y.z menaikkan versi dan menulis changelog. Sebuah pull request membawanya ke main. Penggabungan membuat tag versi dan rilis GitHub. Lalu pull request penggabungan balik membawa commit rilis kembali ke develop.

Publikasi

Setiap artefak masuk ke registri-nya sendiri. Image Docker dibangun di GitHub Actions dan diunggah ke registri kontainer GitHub. Paket Dart dan Flutter masuk ke pub.dev, paket JavaScript ke npm, paket PHP ke Packagist, dan brick Mason kami ke Cloudflare R2. Situs statis disalin ke shared hosting.

Deploy

GitHub Actions terhubung ke server lewat SSH. Server menarik image dari registri, jadi runner tidak pernah mengirim byte image ke server. Docker Compose menjalankannya, dan skrip menunggu sampai kontainer sehat. Lalu smoke test memeriksa situs yang hidup. Bila ada yang gagal, skrip kembali ke versi sebelumnya. Lumbung dan Archipelago memakai deploy blue/green. Traefik memberi HTTPS ke setiap aplikasi. Aplikasi berbagi beberapa layanan di server yang sama: Postgres dan MySQL untuk data, Redis untuk cache, antrean, dan sesi, serta broker MQTT bersama untuk aplikasi realtime.

Pantau

Layanan telemetri kami sendiri, beacon, mengirim data lewat Grafana Alloy ke Grafana Cloud. Dari sana kami mendapat probe uptime dan dashboard. Cadangan harian masuk ke penyimpanan cloud. Rilis Archipelago mengirim pemberitahuan ke Discord.

Satu aturan menjaga semua ini jujur: tidak ada yang membangun image di laptop lalu menyalinnya ke server. Kami pernah melanggarnya pada platform operasional yang dijelaskan di bawah. Setelah menyadarinya, kami memindahkannya ke jalur yang sama, dan sekarang ia dirilis seperti produk lain.

Bagian 1: Brankas rahasia untuk tim dan agen AI

Masalah pertama di tim mana pun adalah rahasia. Kunci tersimpan di pesan obrolan, di berkas .env yang disalin manual, dan di catatan bersama. Saat seseorang keluar, kuncinya tetap ada.

Kami menjalankan Vaultwarden sendiri. Ia memakai protokol Bitwarden, jadi staf memakai alat baris perintah resmi bw. Lima aturan membentuk desainnya:

  1. Satu catatan aman untuk setiap proyek dan lingkungan, dengan nama seperti lumbung/.env.staging. Setiap kolom di dalam catatan adalah satu variabel, dengan nama variabel sebagai nama kolomnya.
  2. Akses diberikan per koleksi. Setiap orang hanya melihat proyek yang ia kerjakan. Untuk mencabut akses, pemilik menghapus orang itu dari koleksi, lalu merotasi rahasia yang bisa ia baca.
  3. Satu perintah menarik catatan ke berkas lokal. Kami tidak pernah meng-commit berkas itu.
  4. Installer-nya bertanda tangan. Pemilik menandatangani skrip dengan kunci yang tidak pernah berada di server. Installer menolak memasang apa pun kecuali tanda tangannya valid dan setiap berkas cocok dengan SHA-256 di daftar bertanda tangan.
  5. .env di server dipasang dari catatan brankas dan tidak pernah diubah manual. Perintah bw-env-deploy lebih dulu menampilkan apa yang akan berubah, berdasarkan nama variabel, tanpa mencetak nilainya. Perintah ini tidak menulis apa pun sampai Anda menambahkan --apply.

Cara engineer atau freelancer mendapatkan berkas .env proyek

Engineer atau freelancer baru hanya butuh .env satu proyek dan tidak lebih. Untuk itu kami membuat tiga perintah kecil di atas Bitwarden CLI. Diagram di bawah menunjukkan seluruh jalurnya, langkah demi langkah.

Alur engineer atau freelancer mendapatkan berkas .env sebuah proyek dari brankas

  1. Pemilik mengundang orang itu ke brankas dan menambahkannya ke koleksi proyek tersebut. Saran kami untuk freelancer: hanya koleksi staging, dengan kunci berhak akses rendah.
  2. Orang itu menjalankan installer bertanda tangan dari situs platform operasional kami: curl -fsSL https://<ops-host>/install.sh | sh. Installer memasang Bitwarden CLI dan perintah kami, dan berhenti bila tanda tangan pemilik atau hash berkas mana pun tidak cocok.
  3. Orang itu menjalankan bw login. Kunci sesi tersimpan di Keychain macOS, jadi tidak ada permintaan kata sandi setiap kali.
  4. Orang itu menjalankan bw-env lumbung staging. Perintah menulis .env.staging di folder proyek, dan berkas itu tidak pernah di-commit.
  5. Saat pekerjaan selesai, pemilik mengeluarkan orang itu dari koleksi dan merotasi kunci yang bisa ia baca.

Ketiga perintah itu: bw-env menarik catatan ke berkas, bw-env-push membuat catatan dari berkas .env yang sudah ada, dan bw-env-deploy menyamakan berkas di server dengan catatan. bw-env-push membuat satu kolom tersembunyi per variabel dan tidak pernah menimpa catatan. Dengan --update, perintah menampilkan nama variabel yang ditambah, diubah, dan dihapus sebelum mengubah apa pun.

Pipeline kami memakai akun brankas terpisah dengan akses baca saja ke satu koleksi bernama CI. Koleksi itu hanya berisi yang dibutuhkan pipeline, tidak pernah rahasia produksi. Sebuah GitHub Action kecil mengubah setiap kolom catatan menjadi variabel lingkungan yang disamarkan.

Sekarang soal agen AI. Mereka bekerja di shell yang sama dengan developer, jadi mereka menghadapi risiko yang sama. Aturan kami: agen boleh memakai nilai, tetapi tidak pernah membaca atau mencetaknya. Agen menjalankan bw-env, berkas jatuh ke disk, dan hanya program yang membaca berkas itu. Nilainya tidak masuk ke prompt atau obrolan. Dry run hanya menampilkan nama, dan itu cukup bagi agen untuk menalar sebuah perubahan.

Ini aturan, bukan tembok. Agen yang bisa menjalankan perintah shell bisa membaca berkas apa pun yang bisa dibaca developer. Karena itu akses dibatasi per proyek, dan kami merotasi rahasia setiap kali ada keraguan.

Bagian 2: Satu platform operasional untuk seluruh siklus klien

Kami tidak menemukan alat yang menangani praktik Indonesia sekaligus. Praktik itu mencakup pemotongan PPh 23 oleh klien, kurs KMK, bea meterai, dan dokumen serah terima BAST dan SPPT. Karena itu kami membangun platform operasional. Platform ini satu program Go dengan antarmuka Vue di dalamnya. Datanya ada di database Postgres bersama, dan proses masuknya lewat penyedia identitas kami sendiri, Rauthy. Kami pernah menulis tentang satu login untuk banyak aplikasi internal.

Platform ini mengikuti satu klien dari kontak pertama sampai invoice terakhir:

  • Klien, dengan portal tempat klien masuk dan melihat proyeknya.
  • Proposal, NDA, dan kontrak, dibuat dari template dalam Bahasa Indonesia atau Inggris.
  • Invoice dalam beberapa mata uang, dengan PPh 23 dan kurs KMK pada tanggal terbit.
  • Buku besar berpasangan (double-entry). Entri tidak pernah diedit. Koreksi dibuat sebagai pembalikan.
  • Proyek dengan tahap sebelum pekerjaan, tahap sesudahnya, dan milestone.

Dokumen saling terhubung: NDA, proposal, kontrak, invoice, BAST, SPPT. Dari dokumen mana pun Anda bisa membuat dokumen berikutnya dengan data yang sudah terisi. Saat kontrak ditandatangani, platform membuat dokumen onboarding dan mengundang klien ke portal. Saat proyek selesai, platform membuat dokumen serah terima.

Halaman Dokumen di platform operasional, dengan data contoh

Email sungguhan hanya terkirim bila APP_ENV=production, dan hanya server yang menyetelnya. Di tempat lain platform memakai kotak surat sandbox yang menangkap setiap pesan. Laptop atau tes tidak bisa mengirim email ke klien.

Bagian 3: Tanda tangan elektronik dengan jejak audit publik

Awalnya kami melirik layanan tanda tangan yang di-host pihak lain. Fitur embed-nya berbayar, dan layanan itu butuh sekitar 2 GB memori di server kecil kami. Jadi kami membangun fitur tanda tangan di dalam platform.

Diagram di bawah menunjukkan alurnya. Setiap penanda tangan menerima tautan pribadi. Jika dokumen mencantumkan nilai di atas Rp5.000.000, dokumen itu butuh bea meterai. Pemilik mengetik nomor seri dari Peruri, karena platform tidak memanggil Peruri. Setiap tindakan masuk ke jejak audit yang hanya bisa ditambah: siapa, kapan, dari alamat mana, dan dari perangkat apa.

Sebagian dokumen perlu segel dari pihak ketiga, misalnya e-meterai atau tanda tangan tersertifikasi. Segel itu dipasang pada PDF sebelum langkah terakhir. Langkah terakhir selalu sama: platform menyimpan sidik jari berkas yang sudah jadi dan mengirimnya ke OpenTimestamps, dan tidak ada yang mengubah berkas setelah itu. Saat ini pemilik mencatat nomor seri e-meterai secara manual. Langkah yang membawa berkas bermeterai kembali ke platform akan menyusul.

Alur dokumen bertanda tangan sampai bisa dibuktikan oleh siapa saja

Saat penanda tangan terakhir selesai, platform membuat PDF final. Platform menambahkan halaman sertifikat dan kode QR, lalu menyimpan sidik jari SHA-256 dari berkas itu. Sidik jari tersebut dikirim ke kalender publik OpenTimestamps. Kalender itu menjangkarkannya di sebuah blok Bitcoin dalam sekitar sehari. Setelah itu, tidak ada yang bisa mengklaim berkas itu dibuat lebih lambat dari blok tersebut.

Kode QR membuka halaman verifikasi publik. Halaman itu menampilkan nomor dokumen, penanda tangan, sidik jari, dan status cap waktu. Judul disembunyikan kecuali pemilik mengizinkannya, karena judul sebuah NDA bisa bersifat rahasia.

Kontrak bertanda tangan di platform, dengan stempel perusahaan

Halaman verifikasi publik dokumen bertanda tangan

Kami pernah membuat satu kesalahan di sini. Awalnya halaman menampilkan tanda “valid” hijau. Padahal halaman itu memeriksa salinan yang disimpan server kami, bukan PDF di tangan pembaca. PDF yang diubah dengan kode QR yang masih berfungsi tetap akan menuju halaman hijau. Sekarang halaman itu menulis “salinan kami masih utuh”. Sebuah formulir memungkinkan pembaca mengunggah PDF mereka sendiri. Server menghitung hash-nya dan membandingkannya byte demi byte, lalu membuang berkasnya.

Ada satu batasan yang perlu kami akui. Ini tanda tangan elektronik tidak tersertifikasi menurut hukum Indonesia (UU ITE). Tanda tangan ini sah, tetapi bobot pembuktiannya lebih rendah daripada tanda tangan dari penyedia tersertifikasi. Pengacara harus meninjau setiap template. Kami menyatakan ini di dalam platform.

Bagian 4: Panduan mengisi SPT Tahunan di Coretax

Bagian ini yang paling kami banggakan.

Setiap tahun, pelaporan SPT adalah pekerjaan paling berat. Formulir lama DJP berupa formulir XFA dari Adobe. Di Mac formulir itu menampilkan layar kosong “Please wait”. Kami menulis parser untuknya dan mengisinya dari pembukuan kami. Lalu DJP memindahkan pelaporan ke Coretax, sistem web dengan formulir panjang. Jadi kami mengganti targetnya.

Halaman Tax forms sekarang membuat semuanya dari buku besar untuk tahun yang Anda pilih:

  • Panduan Coretax. Panduan ini mengikuti layar Coretax pertanyaan demi pertanyaan, dengan jawaban yang diketik di samping setiap pertanyaan.
  • PDF pendukung: laporan keuangan, neraca saldo, jurnal umum, buku besar, rincian biaya, rekapitulasi pendapatan, kredit pajak PPh 23, dan biaya dibayar di muka.
  • Berkas zip berisi CSV untuk konsultan pajak.
  • Angka tahunan, termasuk kerugian fiskal yang dikompensasikan dari tahun sebelumnya.

Halaman Tax forms di platform, dengan angka contoh

Satu halaman Panduan Coretax: setiap pertanyaan dengan jawaban yang diketik

Platform tahu rezim pajak mana yang berlaku di setiap tahun dan menampilkan angka untuk rezim itu. Platform tidak pernah melaporkan apa pun. Setiap angka diberi tanda “verifikasi sebelum melapor”, dan orang yang memahami pajak harus memeriksa angkanya sebelum Anda mengirim.

Kami belajar satu hal dengan cara sulit. Coretax menampilkan kesalahan parsing saat satu kolom tidak berisi angka. Panduan sekarang mencetak nol secara eksplisit di setiap sel. Angka negatif dicetak dengan tanda minus, karena tanda kurung pernah membuat kami mengetik tanda yang salah.

Bagian 5: Apa yang dilihat klien kami

Bagi klien, minggu-minggu pertama dengan vendor baru adalah yang tersulit. Mereka tidak tahu apa yang terjadi berikutnya, siapa berutang apa, atau apakah pekerjaan bergerak. Kami ingin klien melihat jawaban ketiga pertanyaan itu tanpa harus bertanya kepada kami.

Perjalanan klien Banua Coder, dari hari pertama sampai serah terima

Semuanya dimulai saat kontrak ditandatangani. Platform membuat portal klien dan mengirim undangan lewat email.

Email undangan ke portal klien

Klien memasukkan alamat email dan menerima kode enam digit. Tidak ada kata sandi yang harus diingat. Halaman pertama yang mereka lihat adalah daftar onboarding. Beberapa langkah tercentang sendiri dari kejadian nyata: kontrak ditandatangani, NDA ditandatangani, invoice pertama dibayar. Langkah lain dicentang klien: memeriksa kontak, bergabung ke grup obrolan. Langkah dari pihak kami, seperti menerima bahan dari klien, juga tampil.

Beranda portal klien dengan daftar onboarding

Setelah itu klien bisa memantau pekerjaan. Tab Papan adalah daftar tugas proyek yang sebenarnya. Kami menyimpannya di Beads, dan sebuah skrip kecil menyinkronkan cuplikannya ke portal. Tab itu menampilkan progres, empat kolom, prioritas, siapa mengerjakan apa, dan umpan pembaruan terbaru. Sinkronisasi punya aturan privasi bawaan. Tugas berlabel internal tidak pernah keluar dari sisi kami. Komentar yang diawali internal: dibuang. Email pemilik tidak pernah dikirim. Sebuah tugas hanya tampil bila kami memberinya label client-visible.

Papan tugas di dalam portal klien

Tab Proyek menunjukkan gambaran besarnya: apa yang terjadi sebelum pekerjaan, selama, dan sesudahnya. Tab itu memuat milestone dan tanggal target. Dokumen dan invoice ada di tab masing-masing, dan apa pun yang menunggu klien punya tombol Tanda tangani sekarang. Saat proyek selesai, platform membuat draf dokumen serah terima BAST dan SPPT. Kami meninjau dan mengirimnya, klien menandatangani, dan PDF bertanda tangan membawa kode QR dari Bagian 3.

Tab Proyek di portal klien: langkah sebelum pekerjaan, lalu tahap berikutnya

Enam hal sebelum Anda menirunya

  1. Mulai dari buku besar. Invoice, laporan, dan formulir pajak semuanya membaca darinya.
  2. Periksa benda yang dipegang pembaca, bukan hanya salinan Anda sendiri.
  3. Jangan pernah menampilkan angka pajak hasil hitungan sebagai angka final.
  4. Buat rilis tetap membosankan dan sama di mana-mana. Satu jalur untuk setiap produk lebih baik daripada satu skrip pintar untuk setiap aplikasi.
  5. Rancang apa yang dilihat klien pada hari pertama. Daftar yang tercentang sendiri murah dibuat dan menghapus banyak pertanyaan.
  6. Punya sistem sendiri hanya masuk akal bila Anda sanggup merawatnya. Biayanya adalah waktu kami, bukan langganan.

Banua Coder membangun sistem operasional internal seperti ini untuk perusahaan dan instansi pemerintah. Jika Anda menginginkannya, jadwalkan panggilan di banuacoder.com.

Penulis

Fajrian Aidil Pratama

Founder & Director

Fajrian adalah Founder & Director Banua Coder, software engineer dengan pengalaman di mobile engineering, platform, dan digital product development. Latar belakang ini membentuk cara Banua Coder bekerja: lebih terstruktur dalam memetakan masalah, lebih kritis dalam merancang solusi, dan lebih disiplin dalam delivery.

Baca lebih lanjut dari Ryan →

Mulai proyek

Punya sistem yang ingin dibangun?

Jadwalkan diskusi dan ceritakan apa yang ingin Anda luncurkan.