Signing Platform Core API
On this page
- Sekilas
- Yang dikerjakannya
- A. Menjalankan penandatanganan dokumen
- B. Mengelola orang dan identitasnya
- C. Menerbitkan dan mengawasi sertifikat
- D. Mengatur siapa boleh melakukan apa
- E. Membiarkan sistem lain menandatangani lewatnya
- F. Memperlihatkan platform kepada publik
- Antarmuka
- Standar
- Di dalamnya
- Keputusan rancangan
- Spesifikasi
- Terkait
- Istilah
Signing Platform Core API adalah jantung platform penandatanganan dokumen: aplikasi Laravel yang memegang orang, organisasi, sistem client, dan catatan, serta mengorkestrasi setiap service khusus di sekelilingnya. Kerjanya jauh lebih luas dari menandatangani. Ia mengelola akun user beserta identitasnya, organisasi beserta unitnya, sistem eksternal yang menandatangani lewat platform, dokumen beserta penanda tangan dan riwayatnya, stempel tanda tangan, dan sertifikat yang dipakai orang untuk menandatangani — lalu menyerahkan pekerjaan berat menandatangani, merender, menstempel waktu, dan menyimpan kepada service yang dibangun untuk itu.
Inilah satu-satunya module di platform yang milik satu project saja: ia memegang aturan dan data project itu, sementara service yang dipanggilnya bisa dipakai di mana pun. Saya tetap membangun dan menuliskannya sebagai module, supaya platform tetap satu kumpulan bagian yang konsisten dengan satu inti di tengahnya.
Sekilas
| Bahasa & framework | PHP, dengan Laravel, di atas PostgreSQL dan Redis |
|---|---|
| Arsitektur | Stateless Laravel Core |
| Versi | 2.15.1 |
| Status | Stabil, berjalan di production |
| Bentuk | API HTTP dengan worker latar belakang, ditambah halaman depan publik yang dirender di server; antarmuka utamanya single-page application terpisah |
| Kode sumber | Privat |
Yang dikerjakannya
A. Menjalankan penandatanganan dokumen
Dokumen di-upload, diberi satu atau lebih penanda tangan dalam tahap berurutan, lalu ditandatangani masing-masing secara bergiliran. Setiap tanda tangan adalah job di latar belakang: request langsung diterima, dokumen ditandai sedang ditandatangani, dan service signer mengerjakan bagian kriptografinya dengan sertifikat milik penanda tangan sendiri. Hash file yang sudah ditandatangani dicatat, sehingga dokumen bisa ditemukan lagi dari isinya, dan setiap versi bertanda tangan yang baru dirantai ke versi sebelumnya.
B. Mengelola orang dan identitasnya
Akun bisa dibuat langsung atau lewat identity provider eksternal, dilindungi autentikasi dua faktor, dan dikelola lintas perangkat. Sebelum seseorang boleh memegang sertifikat tanda tangan, identitasnya diverifikasi: data pribadi, dokumen identitas, dan tantangan wajah secara langsung, diperiksa oleh peninjau manusia.
C. Menerbitkan dan mengawasi sertifikat
Inti meminta sertifikat dari certificate authority penanda tangan atas nama seseorang, menjaga paling banyak satu sertifikat aktif per orang di tiap organisasi, dan memeriksa status pencabutan secara langsung ke authority itu, lalu memperbarui catatannya sendiri bila jawaban authority berbeda.
D. Mengatur siapa boleh melakukan apa
Organisasi berisi unit, unit berisi anggota, dan role diberi peringkat supaya tak ada yang bisa bertindak atas rekan setingkat atau orang di atasnya. Organisasi bisa menerima anggota secara otomatis dari allowlist alamat e-mail, dan administrator bisa menangguhkan akun tanpa menghapusnya.
E. Membiarkan sistem lain menandatangani lewatnya
Sistem client — pelanggan software-as-a-service platform ini — memanggil API client tersendiri dengan secret, origin yang diizinkan, dan izin per operasi miliknya sendiri. Client internal yang tepercaya boleh menautkan user secara langsung; client eksternal butuh persetujuan user. Hasilnya dikirim kembali ke tiap client lewat webhook, dikirim di latar belakang dan dicatat sampai berhasil.
F. Memperlihatkan platform kepada publik
Halaman beranda publik dirender oleh inti itu sendiri, dengan konten yang bisa diperbarui administrator, supaya mesin pencari bisa mengindeksnya; aplikasi tempat orang bekerja tinggal di repository-nya sendiri.
Antarmuka
| Bidang | Yang dibukanya |
|---|---|
| Autentikasi | login, refresh token yang berotasi, dua faktor, identity provider eksternal, signing key publik dari token-tokennya |
| User | akun, perangkat, role, template stempel |
| Organisasi | organisasi, unit, anggota, allowlist e-mail |
| Identitas | verifikasi identitas, tantangan wajah, antrean peninjau |
| Sertifikat | permintaan, persetujuan, pencabutan, status langsung |
| Dokumen dan file | upload lewat link berumur pendek, penanda tangan, penandatanganan, versi bertanda tangan |
| Sistem client | pengelolaan client, dan API client tersendiri dengan autentikasinya sendiri |
| Administrasi | dashboard, job yang gagal, konten halaman publik |
| Readiness | satu endpoint yang memeriksa database, cache, storage, dan setiap service yang dibutuhkan inti |
Standar
| Standar | Yang dijaminnya di sini |
|---|---|
| JSON Web Token dengan RS256, dan JWKS yang diterbitkan | satu format token untuk setiap login, bisa diverifikasi service mana pun tanpa memanggil inti |
| OAuth 2.0 dan OpenID Connect, dengan PKCE | login lewat provider eksternal, ditukar menjadi token milik inti sendiri |
| TOTP (RFC 6238) | autentikasi dua faktor dengan aplikasi authenticator apa pun |
| OCSP (RFC 6960) | status pencabutan langsung untuk setiap sertifikat yang dipakai platform |
| Presigned URL, AWS Signature Version 4 | file berpindah antara browser dan storage tanpa melewati inti |
| W3C Trace Context dan OpenTelemetry | satu trace dari request user melewati setiap service dan job latar belakang |
| UUIDv7 | identitas publik dan request id yang terurut waktu dan tak membuka urutan internal |
Di dalamnya
Inti ini mengikuti Stateless Laravel Core: node tak memegang apa pun, pekerjaan lambat berjalan sebagai job di antrean, file tak pernah menyentuh server, setiap login berakhir dengan token milik inti sendiri, dan setiap request, job, serta panggilan keluar di-trace. Tiap service khusus dijangkau lewat satu class miliknya sendiri, dengan konfigurasi, timeout, dan keluarga error-nya sendiri.
Keputusan rancangan
Inti memutuskan; service khusus yang bekerja. Menandatangani, menstempel waktu, menerbitkan sertifikat, merender thumbnail, menantang wajah, menyimpan file, dan mencari data wilayah masing-masing menjadi milik service yang dibangun untuk tugas itu, dan inti mengorkestrasinya. Bila satu service tak punya yang dibutuhkan inti, saya memintanya di service itu, tak mengakalinya di sini — endpoint batch yang kini ditawarkan service storage ada karena inti membutuhkannya. Data wilayah dulu tinggal di tabel milik inti; kini ia pindah ke service alamat, dan organisasi menyimpan snapshot wilayahnya, bukan foreign key, sehingga perubahan kode wilayah resmi tak pernah diam-diam merusak record yang sudah ada.
Penandatanganan tak pernah membuat siapa pun menunggu. Request penandatanganan diperiksa sebelum masuk antrean — passphrase penanda tangan diverifikasi, jadi job tak pernah berangkat dari passphrase yang salah — lalu langsung diterima, dengan dokumen ditandai sedang ditandatangani, bukan sudah ditandatangani. Passphrase itu berjalan terenkripsi melewati antrean. Webhook ke client yang gagal tak pernah membatalkan tanda tangan; pengirimannya diulang dan dicatat terpisah.
Data pribadi dilindungi sebagai data, bukan hanya saat dikirim. Nomor telepon, data kelahiran, nomor identitas, dan secret dua faktor dienkripsi di database, dan nomor identitas bisa dicari tanpa mendekripsi apa pun. Nomor identitas polos tak pernah muncul di respons login, karena di sana ia akan mengendap di storage browser dan log. Satu registry menjadi satu-satunya tempat yang memutuskan apakah nomor identitas sudah terpakai, sehingga tak ada dua jalur kode yang bisa berbeda pendapat. Foto identitas yang ditampilkan ke peninjau membawa watermark yang menandai penayangnya, sehingga gambar yang bocor bisa ditelusuri, dan foto wajah dihapus dari storage begitu verifikasi disetujui.
Tak ada yang membocorkan apa yang ada. Identitas publik berupa UUID acak, tak pernah urutan internal, sehingga record tak bisa dihitung satu per satu. Endpoint yang bisa membocorkan apakah satu akun ada — reset password, e-mail verifikasi — menjawab dengan cara yang sama dalam kedua keadaan. Tindakan yang berdampak panjang mewajibkan password dimasukkan lagi, dan administrator tak bisa bertindak atas rekan setingkat atau role di atasnya.
Setiap versi bertanda tangan tetap tersambung. Hash tiap file yang ditandatangani disimpan, sehingga dokumen bisa dikenali dari file-nya saja. Ketika dokumen bertanda tangan di-upload lagi untuk tanda tangan berikutnya, versi barunya dirantai ke hash sebelumnya, dan karena byte file tak pernah melewati inti, hash itu dibaca kembali dari storage, tak dihitung dari upload yang tak pernah dilihat inti.
Dua jenis client, dua tingkat kepercayaan. Client internal — sistem yang dijalankan organisasi yang sama — dipercaya menautkan user-nya secara langsung dan menerima izin bawaan. Client eksternal harus mendapat persetujuan tiap user lewat token sekali pakai dan dibatasi pada operasi yang diizinkan baginya, diperiksa pada setiap panggilan. Secret client disimpan dalam bentuk hash, dan user yang dirujuk client dikenali lewat rujukan yang diturunkan platform sendiri, bukan identitas karangan client.
Sertifikat diperiksa di tempat asalnya. Status pencabutan ditanyakan langsung ke certificate authority, dan bila jawabannya berbeda dari catatan inti, catatan itulah yang mengikuti authority, dengan alasan pencabutan yang sebenarnya ikut disimpan. Sertifikat milik authority itu sendiri diambil sekali dan di-cache, tak disimpan sebagai file di server.
Storage selalu terhitung. Setiap object key yang dirujuk database dikenal satu indeks, tak ada yang dihapus dari storage tanpa bertanya kepadanya lebih dulu, dan audit read-only membandingkan storage dengan database sebelum apa pun disapu.
Spesifikasi
| Masukan | Request dari aplikasi web, dari sistem client, dan dari administrator |
|---|---|
| Hasil | Respons JSON, dokumen bertanda tangan di storage, sertifikat atas nama user, webhook ke sistem client, e-mail |
| Bergantung pada | PostgreSQL, Redis, dan service platform untuk storage, alamat, sertifikat, stempel waktu, penandatanganan, thumbnail, dan tantangan wajah |
| Kerja latar belakang | Job di antrean untuk penandatanganan, thumbnail, webhook, e-mail, dan pemrosesan allowlist |
| Keamanan | Token RS256 dengan refresh token yang berotasi, autentikasi dua faktor, rate limit di Redis, data pribadi terenkripsi, role berperingkat |
| Observability | Trace, log, metrics, dan event audit OpenTelemetry, berlanjut melintasi setiap service dan job |
| Berjalan sebagai | Container berisi web server dan worker antrean di bawah satu supervisor, ditambah kapasitasnya dengan menambah salinan |
Terkait
Service storage tempat setiap file, stempel, dan dokumen bertanda tangan berpindah.
Service alamat yang memasok data wilayah untuk organisasi.
Certificate authority yang menerbitkan sertifikat tiap penanda tangan dan menjawab pemeriksaan pencabutan.
Timestamp authority di balik tanggal setiap tanda tangan.
Root publisher di puncak rantai kepercayaan platform.
Signer yang mengubah setiap request di antrean menjadi tanda tangan PDF jangka panjang.
Renderer yang memberi setiap dokumen thumbnail halaman pertamanya.
Tantangan wajah yang membuktikan seseorang hadir selama verifikasi identitas.
Ke mana trace satu request yang melewati semua service ini berakhir.
Istilah
- Orkestrasi
- Mengoordinasikan beberapa service supaya bersama-sama menuntaskan satu pekerjaan, tanpa mengerjakan pekerjaan itu sendiri.
- Enumerasi
- Menemukan record atau akun mana yang ada dengan mencoba identitas satu per satu lalu membandingkan jawabannya.
- Webhook
- Request yang dikirim satu sistem ke alamat sistem lain untuk memberitahukan bahwa sesuatu telah terjadi.
- Software as a service
- Software yang dipakai pelanggan lewat server penyedianya, di sini dengan menyambungkan sistem milik mereka ke platform.
Technologies covered
- PHP
- Laravel
- PostgreSQL
- Redis
- OpenTelemetry
- OAuth 2.0