Skip to content

Audit Duitku Laravel SDK — 22 Oktober 2026 ​

Package perlu memperbarui signature pembayaran dan memperketat penerimaan callback sebelum menambah fitur besar. Struktur DTO, service Laravel, dan event sudah memberi fondasi untuk pengalaman integrasi yang lebih lengkap daripada wrapper HTTP biasa.

Audit membaca kode pada commit 8208ee62d0dd66713f698f94285a4a53837d0899. Temuan dan reproduksi di dokumen ini adalah catatan historis untuk commit tersebut. Perbaikan sesudah audit dijelaskan dalam panduan migrasi; reproduksi historis tidak termasuk suite test rilis baru.

Hasil yang sudah diverifikasi ​

  • Dependabot aktif: GitHub Actions dan npm sudah membuat PR, termasuk update Vue. Composer gagal menyelesaikan graph dependensi: run dan log. Ini masalah dependensi project, bukan kebutuhan token tambahan dari pemilik repository.
  • composer validate berhasil; 55 file PHP lolos syntax check pada pemeriksaan awal.
  • Instalasi dari composer.json asli gagal pada PHP 8.4.1. Solver melaporkan konflik yang melibatkan Larastan 2, Testbench, dan Illuminate. Audit belum mengisolasi seluruh kombinasi yang menyebabkan konflik.
  • Di salinan sementara, Larastan dihapus seperti pada workflow tests, lalu Laravel 12/Testbench 10/Pest 4 dipilih. Dengan source package tetap sama, seluruh 54 test bawaan berhasil, 149 assertion. Versi terpasang: Laravel 12.70.1, Testbench 10.12.0, Pest 4.7.8.
  • Ada 20 pemeriksaan tambahan: 18 gagal memenuhi kontrol yang diusulkan, dua berhasil. Ini bukan 18 kerentanan terpisah; beberapa menguji kontrak baru atau kewajiban aplikasi pengguna.
  • Signature callback clearing cocok dengan formula dokumentasi yang diperiksa. Blade component juga berhasil dirender sebelum pemanggilan facade pada Testbench. Keduanya tidak dicatat sebagai bug.

Semua transaksi memakai data sintetis dan Http::fake(). Tidak ada pemanggilan API transaksi, penggunaan kredensial merchant, atau pengujian terhadap production Duitku.

Acuan dan perbedaan sumber ​

Overview resmi membedakan API V2 dan POP. Kedua jalur perlu diuji dengan kontrak masing-masing.

Changelog API mencatat migrasi HMAC pada April 2026, penambahan customerName pada Juni 2026, dan pengurangan QRIS Gudang Voucher pada September 2026. Dokumentasi pembayaran yang diperiksa sekarang memakai HMAC-SHA256. Sebaliknya, SDK resmi pada commit bf182ec masih memakai formula lama di Api.php dan Pop.php.

Karena sumber berbeda, status audit adalah ketidakcocokan kode dengan kontrak terdokumentasi, bukan bukti bahwa semua akun merchant sudah menolak signature lama. Konfirmasi sandbox dengan akun yang sesuai tetap diperlukan sebelum rilis migrasi. Jangan menjadikan SDK resmi satu-satunya oracle kontrak.

Temuan dan prioritas ​

P1 berarti didahulukan sebelum rilis kompatibilitas baru. P2 berarti dibenahi pada tahap pengerasan berikutnya. P3 berarti konsistensi dokumentasi dan kemudahan pengembangan.

A1 — P1: Signature pembayaran tertinggal dari dokumentasi ​

Status: confirmed pada kode dan pengujian kontrak lokal; penerimaan server belum diuji.

src/Concerns/InteractsWithApi.php:12, src/Duitku.php:49, src/Duitku.php:70, src/Duitku.php:94, dan src/Services/Pop.php:35 menghasilkan MD5 atau SHA256 dengan secret yang digabung ke pesan. validateCallback() juga hanya menerima MD5. Formula HMAC-SHA256 terdokumentasi menggunakan secret sebagai key, bukan bagian pesan. API, POP.

Dampaknya adalah risiko request ditolak dan callback baru tidak diterima. Tiga pemeriksaan HMAC lokal gagal. Pengujian signature lama tidak membuktikan kesesuaian dengan provider sekarang.

Kontrol: pisahkan signer per protokol. Jadikan HMAC sebagai target migrasi pembayaran; legacy hanya melalui pilihan eksplisit bila kompatibilitas akun membutuhkannya. Jangan mencoba algoritma lama otomatis setelah kegagalan. Disbursement tetap memakai kontraknya sendiri, yang masih mendokumentasikan SHA256.

Uji penerimaan: fixture HMAC dengan key/pesan tetap harus cocok; perubahan satu field yang ditandatangani harus ditolak. Jalankan checkout, status, daftar metode, dan callback pada sandbox sebelum mengubah default rilis.

A2 — P1: Kredensial kosong masih bisa menerima callback ​

Status: confirmed, direproduksi lokal.

src/Support/DuitkuConfig.php:14 dan :19 mengembalikan string kosong ketika kredensial tidak ada. src/Duitku.php:149 tetap menghitung signature dan :166 memproses event.

Jika aplikasi menerbitkan route callback dengan konfigurasi tersebut, pengirim anonim dapat membuat signature tanpa mengetahui secret. Pengujian sintetis menunjukkan handleCallback() tidak menolak payload saat kedua kredensial kosong. Ini bergantung pada deployment salah konfigurasi; audit tidak mengklaim akun dengan secret terisi dapat ditembus tanpa secret.

Kontrol: gagalkan operasi sebelum validasi atau request bila merchant code/API key kosong. Terapkan pemeriksaan kredensial sesuai kebutuhan tiap service.

Uji penerimaan: konfigurasi kosong melempar configuration exception dan tidak mengirim event/request; callback valid dengan konfigurasi lengkap tetap diterima.

A3 — P1: Callback belum mengikat identitas dan bentuk payload dengan ketat ​

Status: confirmed, direproduksi lokal.

src/Duitku.php:153 menggunakan merchant code konfigurasi tanpa memeriksa kesamaannya dengan merchant code payload. src/Data/CallbackRequest.php:40 mengubah amount menjadi integer sebelum verifikasi. Payload dengan amount 10000junk masih lolos bila membawa signature legacy untuk 10000. Payload dengan merchant code yang diubah juga lolos memakai signature valid yang sudah dimiliki pengirim. resultCode yang hilang justru menghasilkan event gagal.

Eksploitasi perubahan payload ini memerlukan akses ke signature valid atau kondisi A2; bukan kemampuan membuat signature baru untuk merchant dengan secret kuat.

Kontrol: validasi field wajib, tipe, representasi nominal, merchant identity, dan himpunan status sebelum membentuk DTO. Verifikasi signature dari nilai yang sudah lolos validasi tanpa normalisasi lossy; gunakan hash_equals() untuk pembandingan.

Uji penerimaan: merchant berbeda, nominal malformed, signature salah, dan status hilang ditolak tanpa event; callback lengkap valid tetap diterima. Unknown field dapat dipertahankan sebagai metadata agar penambahan provider tidak hilang.

A4 — P1: Finalisasi pembayaran belum memiliki perlindungan replay dan verifikasi order ​

Status: confirmed untuk perilaku SDK; dampak bisnis bergantung pada listener aplikasi.

src/Duitku.php:175 mengirim ulang event setiap kali payload dipanggil; dua callback identik menghasilkan dua event pembayaran. :178 langsung mempercayai resultCode. Field itu tidak masuk pesan signature saat ini. Dengan satu payload bertanda tangan yang sudah diketahui, perubahan result code tidak memicu pengecekan status independen.

Contoh listener di docs/guide/callback-system.md tidak mencocokkan nominal order, tidak memakai transaksi/unique constraint, dan tidak menjelaskan perlindungan status final. SDK stateless tidak harus menyimpan semua order, tetapi contoh yang direkomendasikan harus menjelaskan kewajiban tersebut.

Kontrol: minimal, contoh listener idempotent dan pencocokan merchant/order/nominal/reference. Untuk mode verifikasi lebih ketat, ambil status dari provider di luar transaksi database, kemudian lakukan transisi order atomik. Kunci deduplikasi harus mempertimbangkan identitas pembayaran; jangan menggabungkan semua pembayaran berbeda hanya karena order ID sama.

Uji penerimaan: dua delivery bersamaan hanya memberi satu efek bisnis, amount berbeda ditolak, status gagal tidak menurunkan order paid, dan callback sukses sah tetap memproses pembayaran. Uji pengulangan event saat ini gagal terhadap kebijakan deduplikasi yang diusulkan; ini bukan janji exactly-once dari SDK sekarang.

A5 — P1: Retry global juga mengulang operasi tulis ​

Status: confirmed untuk pengulangan HTTP; duplikasi transfer nyata belum dibuktikan.

src/Http/Client.php:26 menerapkan retry() pada seluruh request. Client yang sama digunakan checkout, cash out, dan eksekusi transfer. Dengan retry_times=2, respons 500 diikuti 200 menghasilkan dua POST dalam pengujian. Default retry adalah nol, sehingga risiko muncul setelah opsi diaktifkan.

Kontrol: kebijakan retry per operasi. Untuk status/read-only, tentukan retry terbatas. Untuk invoice/payout, pertahankan identitas operasi dan selesaikan hasil ambigu melalui status/reconciliation sesuai kontrak provider. Jangan menganggap timeout berarti operasi belum terjadi.

Uji penerimaan: simulasi write berhasil tetapi respons hilang, lalu pastikan tidak ada eksekusi write baru secara buta; read-only yang transient tetap dapat pulih. Keselamatan pengulangan transfer perlu dikonfirmasi provider.

A6 — P2: Log request menyimpan informasi pelanggan dan signature ​

Status: confirmed, direproduksi lokal.

Ketika logging aktif, src/Http/Client.php:32 menulis seluruh body JSON. Jalur tersebut membawa email, nomor telepon, alamat, data rekening, atau credential account-link sesuai request. Pengujian membuktikan email sintetis dan signature masuk konteks log. Ini bukan kebocoran API key langsung pada request pembayaran, dan log tidak aktif secara default.

Kontrol: allow-list metadata operasional; redaksi signature, credential/token, rekening, dan data pelanggan. Atur masa simpan di aplikasi pemilik log.

Uji penerimaan: data sensitif sintetis tidak muncul di log, sementara operation ID, URL yang aman, durasi, dan kategori hasil tetap tersedia. Pembaca log tidak boleh mendapat kemampuan replay tambahan dari rekaman SDK.

A7 — P2: Reference POP masuk konteks JavaScript tanpa encoding JavaScript ​

Status: confirmed pada render HTML dan eksekusi handler lokal; keterjangkauan penyerang conditional.

resources/views/components/pop.blade.php:3 menyisipkan reference ke literal JavaScript dalam onclick. HTML attribute escaping tidak mengamankan literal JavaScript setelah browser mendekode entitas. Pengujian merender reference sintetis, membaca atribut melalui DOM, dan menjalankan handler dengan stub checkout; flag injeksi berubah menjadi true.

Penyerang perlu mengendalikan reference, misalnya integrasi aplikasi mengambilnya langsung dari query pengguna. Alur normal yang hanya memakai reference aman dari server provider belum membuktikan keterjangkauan serangan.

Kontrol: pisahkan data dari kode, misalnya data-reference dan event listener. Gunakan serializer JavaScript bawaan bila data harus dimasukkan ke JavaScript. Hindari script berulang per instance dan dukung CSP.

Uji penerimaan: kutip, backslash, dan karakter HTML tetap menjadi data; reference normal masih membuka checkout. Uji DOM/JavaScript cukup untuk bug ini; tidak perlu mengirim transaksi browser nyata.

A8 — P2: DTO tokenisasi dan metadata belum sesuai kontrak ​

Status: confirmed pada serialisasi dan pembacaan dokumentasi.

src/Data/CreditCardDetail.php:20 membatasi saveCardToken menjadi boolean. Input integer 2 berubah menjadi true. PaymentRequest menaruh merchantCustomerId di top level, sementara CustomerDetail tidak punya propertinya. Kontrak POP menempatkan customer ID di dalam customer detail dan membedakan mode token integer 1/2. Objek POP.

CallbackRequest juga belum menyimpan customerName; enum masih menawarkan GQ. Changelog API.

Kontrol: DTO/enum token mode yang tepat, customer ID pada objek yang benar, metadata callback yang tidak hilang, serta deprecation channel lama. Pertahankan raw-array escape hatch dengan validasi; jangan memutus dukungan tanpa kebijakan rilis.

Uji penerimaan: mode 1 dan 2 berbeda pada JSON, customer ID berada di lokasi tepat, callback metadata round-trip, dan channel discontinued tidak dipromosikan sebagai tersedia. Belum ada kebutuhan menghidupkan kembali field subscription lama.

A9 — P2: Respons rusak atau HTTP gagal dapat menjadi hasil yang tampak normal ​

Status: confirmed, direproduksi lokal.

src/Data/PaymentResponse.php:44 memperlakukan status kosong sebagai keberhasilan, sementara fromArray() memberi default string kosong untuk reference/URL. Fake HTTP 200 dengan body error lolos sebagai objek checkout.

src/Duitku.php:137 dan src/Services/Disbursement/Transfer.php:155 memetakan respons pool tanpa memeriksa status HTTP. Fake HTTP 500 menjadi DTO tanpa status transaksi yang berguna. paymentMethods() juga tidak memeriksa HTTP status sebelum mengembalikan daftar kosong.

Kontrol: bedakan transport error, business rejection, malformed response, dan pending yang sah. Validasi field sukses per endpoint; jangan sekadar mewajibkan statusCode yang mungkin tidak ada di semua respons API. Batch sebaiknya mengembalikan hasil/error per input dengan identitas stabil.

Uji penerimaan: HTTP 500, JSON rusak, shape error 200, business error 200, serta respons valid tanpa field opsional mendapat hasil yang tepat. Structured per-item failure dapat menggantikan exception pada batch; assertion audit saat ini memakai exception untuk menunjukkan tidak adanya failure eksplisit.

A10 — P2: Pool melewati konfigurasi HTTP dan tidak membatasi fan-out ​

Status: confirmed pada konfigurasi dan pengujian timeout; kapasitas belum diukur.

checkStatuses() dan bulkInquiry() membuat request langsung melalui pool. Timeout konfigurasi 7 detik tetap menjadi default framework 30 detik pada pengujian. Logging/retry dari client package juga tidak diterapkan. Tidak ada batas concurrency atau ukuran batch.

Kontrol: konfigurasi request bersama dan concurrency terbatas, hasil yang tetap terikat order/rekening, serta penanganan partial failure. Gunakan kemampuan framework yang tersedia pada versi yang didukung. Dokumentasi disbursement memperingatkan polling status berulang dapat terkena rate limit. Inquiry status.

Uji penerimaan: konfigurasi mencapai request, satu kegagalan tidak menghilangkan hasil lain, dan jumlah request aktif tidak melewati batas. Klaim README bahwa 50/100 transaksi selesai di bawah satu detik belum punya bukti benchmark dalam audit ini.

A11 — P2: Graph development menghambat update dan pemeriksaan kompatibilitas ​

Status: confirmed dari solver lokal dan Dependabot.

composer.json:14 belum mengizinkan Laravel 13; :21 belum menyediakan Testbench untuk jalur tersebut; :22–:23 masih memakai PHPStan 1/Larastan 2. Workflow tests menghapus Larastan sebelum resolve dependensi, sedangkan workflow static analysis memakai manifest lengkap. Ini membuat test yang hijau tidak membuktikan developer dapat menginstal graph lengkap.

Kontrol: tentukan dukungan Laravel/PHP yang masih dipelihara, selaraskan tooling, dan uji instalasi manifest asli selain lane framework. Tambahkan Laravel 13 setelah resolusi dan pengujian nyata berhasil. Jangan menyembunyikan konflik dengan mematikan audit advisory.

Uji penerimaan: fresh dependency resolution, static analysis, formatter, dan matriks test berhasil pada kombinasi yang dideklarasikan. Untuk Composer library tanpa lockfile, minor yang sudah diizinkan constraint tidak selalu menghasilkan perubahan manifest; itu perilaku yang wajar.

A12 — P3: Dokumentasi, konfigurasi, dan facade memiliki drift ​

Status: confirmed dari source.

  • docs/guide/usage-disbursement.md:88 memakai method yang tidak ada, dan :105 memakai bentuk transfer lama. Gunakan transfer()->inquiry() dan transfer()->execute().
  • README menyebut composer test, tetapi composer.json tidak mendefinisikan script itu.
  • default_expiry punya getter, tetapi tidak digunakan checkout/POP. Pengujian default 17 menit tidak menemukan field expiry pada payload.
  • Anotasi facade menyebut Collection untuk method yang mengembalikan array, dan belum mencantumkan seluruh entrypoint utama.
  • Request pembayaran dapat dibuat tanpa URL callback/return dan tanpa metode pembayaran API. Pisahkan validasi persyaratan API dan POP; jangan menebak aturan channel dari satu nominal minimum global.

Kontrol dan uji: jalankan snippet dokumentasi dengan fake provider, periksa public API yang dipanggil, dan uji default/override expiry. Memakai satu nilai default untuk semua channel juga perlu menyesuaikan batas channel.

Hal yang masih perlu konfirmasi provider ​

src/Services/Pop.php:58 dan :90 menggunakan endpoint status/daftar metode dengan header timestamp. SDK resmi menggunakan kontrak berbeda untuk operasi tersebut: Pop::transactionStatus() mengirim merchant code/signature di body, dan Pop::getPaymentMethod() menuju jalur API V2. Implementasi SDK resmi.

Perbedaannya confirmed; dukungan endpoint dan payload package saat ini oleh server masih suspected. Tidak ada feature test untuk kedua method tersebut. Verifikasi kontrak di sandbox atau dengan Duitku sebelum menambah klaim dukungan. Teks content-type pada dokumentasi API juga tidak selalu konsisten dengan contoh JSON; audit tidak menyarankan perubahan encoding berdasarkan satu label saja.

Batas kepercayaan dan tanggung jawab ​

SDK tidak menyediakan route aplikasi, user login, tenant model, atau database order. Otorisasi pengguna yang boleh melakukan checkout/payout tetap milik aplikasi pemakai.

PermukaanIdentitas/inputKontrol saat iniPemilik kontrol lanjutan
Checkout/POPPemanggil server dan payment DTOSignature outbound, host tetap, TLS client defaultAplikasi mengotorisasi order/nominal; SDK memvalidasi konfigurasi dan kontrak
Status/daftar metodeOrder ID/nominal dari aplikasiSignature, timeout untuk request tunggalAplikasi membatasi akses order; SDK menangani error dan batas batch
Transfer/clearing/cash outPemanggil server, rekening, nominal, credential merchantSignature outbound; inquiry dan execute terpisahAplikasi mengotorisasi payout dan menyimpan operation identity; SDK menerapkan retry sesuai operasi
Callback pembayaranPOST dari jaringan tidak tepercayaSignature legacy; kemudian eventSDK A1–A3; aplikasi mengikat order/nominal dan memproses efek idempotent
Callback clearing/cash outPayload eksternalMethod validasi signature di serviceAplikasi memanggil validator, memeriksa status, dan menjaga transisi final
Blade POPReference dan attributes dari aplikasiHTML escapingSDK mengamankan konteks JavaScript; aplikasi memasok reference dari sumber yang dipercaya
Log/buildData request, dependency, CILogging opt-in, workflow terpisahSDK melakukan redaksi; maintainer mengontrol branch, PR, dan build inputs

Asset yang dilindungi: status paid, instruksi transfer, credential/token, data pelanggan/rekening, serta integritas package dan dokumentasi. Ancaman lokal diuji dengan pengirim anonim, pemegang salinan payload sah, pembaca log, dan pengendali reference sebagai kemampuan yang berbeda.

Dependency dokumentasi ​

npm audit --package-lock-only --ignore-scripts --json melaporkan 9 entri dependency terdampak: 7 high, 2 moderate. Angka ini memakai klasifikasi scanner, mencakup severity turunan, dan tidak berarti ada sembilan jalur eksploitasi checkout.

Lockfile memuat Vue/server-renderer 3.5.27, VitePress 1.6.4, Vite 5.4.21, esbuild 0.21.5, Rollup 4.57.0, PostCSS 8.5.6, nanoid 3.3.11, dan source-map-js 1.2.1.

Triage awal: advisory Vue SSR memerlukan data atribut yang dipengaruhi penyerang; Rollup berkaitan dengan input build; esbuild mengenai development server. Belum ada jalur input penyerang yang dibuktikan pada website statis project ini. Semua berada di tooling dokumentasi, bukan dependency runtime PHP pengguna package. Advisory PostCSS/nanoid/source-map-js/Vite lain masih memerlukan triage keterjangkauan lebih lanjut.

Perbarui toolchain melalui PR dan uji build; jangan menjalankan npm audit fix --force tanpa meninjau perpindahan major. Nilai fixAvailable: false berarti scanner tidak menawarkan perbaikan otomatis dalam graph saat ini, bukan bukti tidak ada solusi. Instalasi Composer sementara melaporkan nol advisory untuk graph Laravel 12 yang dipilih; hasil itu tidak mencakup seluruh kombinasi yang dijanjikan package.

Peluang fitur ​

Nilai tambah paling dekat adalah integrasi Laravel yang menjaga pembayaran tetap benar saat ada kegagalan. Usulan berikut belum diimplementasikan atau dibuktikan lebih unggul lewat benchmark.

UrutanFiturManfaat dan batas cakupanBukti penerimaan
1Callback verification dan panduan listener idempotentValidasi ketat, pencocokan order/amount, optional status verification. Mulai dari listener aplikasi; persistent inbox menjadi modul opt-in bila dibutuhkanDuplicate delivery/concurrency hanya sekali memberi efek; unpaid tidak menjadi paid
2Hasil batch bertipe dengan concurrency terbatasHasil sukses/error per input, timeout konsisten, tanpa membanjiri providerPartial failure tetap bisa ditelusuri; batas request aktif terbukti
3Diagnostic command dan fake provider untuk testPemeriksaan konfigurasi tanpa menampilkan secret; fixture kontrak versi baru; helper assertion requestSalah config gagal jelas; fixture contract mendeteksi signature/payload berubah
4POP component yang mendukung events dan CSPJS dimuat sekali; opsi bahasa/currency dan callback browser menjadi custom events. Browser event tetap petunjuk UI, bukan bukti paidDua component tidak menggandakan script; callback UI tidak mengubah status order
5Tokenisasi kartu dan lifecycle kartu sebagai modul terpisahLengkapi DTO dahulu, lalu layanan token management/charge/void/refund/capture berdasarkan hak akses merchantNominal refund, pemilik token, state capture, dan hasil ambigu diuji
6SNAP sebagai modul terpisahVA lifecycle, account binding/direct debit, refund debit, dan QRIS. Credential, signature, uang, serta state berbeda dari API V2Fixture protokol, token refresh, signature notify, dan idempotensi lolos; baru kemudian sandbox

Opsi frontend tersedia pada kontrak POP. Direct Credit Card mendokumentasikan token management, void/refund, dan delay capture; jangan menjanjikan refund universal untuk semua metode bayar. Beberapa kemampuan memerlukan aktivasi merchant.

SNAP Duitku menawarkan VA lifecycle, direct debit/account binding, debit refund, dan QRIS. Dokumentasinya juga mencatat penambahan paid time, fee, dan expiry pada 2026. Auto debit OVO memerlukan pendaftaran, dan penggunaan SNAP memiliki proses onboarding tersendiri. Fitur ini layak dievaluasi sebagai fase lanjutan, bukan tambahan kecil pada signer lama.

Fitur nomor 1–4 merupakan rekomendasi desain audit ini, bukan klaim bahwa library provider menjanjikan exactly-once atau bahwa semua kemampuan tersebut baru diluncurkan pada 2026. Source lokal sudah memberi DTO/events/disbursement; perbandingan hanya terhadap SDK PHP resmi yang disebutkan pengguna, bukan seluruh library Duitku di semua bahasa.

Urutan implementasi yang disarankan ​

  1. Pulihkan dependency resolution dan tambahkan fixture kontrak pembayaran terbaru. Selesaikan A1–A5 sebelum rilis yang dipromosikan untuk pembayaran production.
  2. Perbaiki encoding POP, redaksi log, DTO, respons error, serta konfigurasi pool. Selaraskan dokumentasi dan tambah lane Laravel 13 setelah tooling siap.
  3. Lengkapi fitur Laravel nomor 1–4. Ukur beban batch dan jumlah request; hapus klaim performa tanpa benchmark yang dapat diulang.
  4. Validasi kebutuhan merchant sebelum membangun lifecycle kartu atau SNAP. Pisahkan kontrak dan kredensial; hindari memaksa seluruh consumer mengadopsi penyimpanan/queue baru.

Reproduksi dan cakupan yang belum diuji ​

Test audit disimpan sebagai AuditRegressionTest.php dan AuditBladeTest.php. File itu sengaja berada di luar tests/, sehingga tidak mengubah suite CI package. Assertion yang gagal menunjukkan kontrol yang belum tersedia; jangan memasukkannya ke suite wajib sebelum implementasi dan kebijakan API disepakati. Node.js diperlukan untuk satu pemeriksaan konteks JavaScript.

Untuk mengulang, salin project ke direktori sementara tanpa vendor dan .git. Di salinan itu, hapus Larastan seperti workflow tests; pilih Laravel framework ^12.0, Testbench ^10.0, Pest/plugin Laravel ^4.0, lalu jalankan composer update --no-interaction --prefer-dist --no-scripts. Jalankan suite bawaan sebelum menyalin file reproduksi ke tests/Feature/.

sh
vendor/bin/pest --no-coverage --do-not-cache-result
# Setelah baseline selesai dan file reproduksi disalin:
vendor/bin/pest tests/Feature/AuditRegressionTest.php tests/Feature/AuditBladeTest.php --no-coverage --do-not-cache-result

Tidak ada test bawaan yang dihapus, dilonggarkan, atau di-skip. Tidak ada perbaikan produksi atau implementasi fitur baru dalam audit ini. Source package di salinan audit sama dengan source repository.

Belum diuji: server sandbox/production, variasi konfigurasi akun merchant, transaksi uang nyata, replay jaringan, seluruh PHP/Laravel matrix, static analysis dengan graph yang dipulihkan, build dokumentasi setelah upgrade, dan akses branch protection/secrets repository. Autodiscovery provider pada aplikasi Laravel terpasang penuh juga belum diperiksa terpisah dari Testbench. Audit tidak membuktikan performa, bebas kerentanan, atau kepatuhan menyeluruh.

Released under the MIT License.