Antonius Felix
AI & EngineeringHTML, CSS, JavaScript native

Reproduksi clean-room: membangun image tool original yang sah

Oct 13, 2026/13 min read/clean-room, browser, image-processing, aksesibilitas, pengujian

Membuat aplikasi dengan perilaku serupa tidak harus berarti menyalin aplikasi lain. Pengguna membutuhkan hasil, misalnya mengubah gambar menjadi grayscale lalu menyimpannya, bukan salinan panel, nama menu, atau identitas vendor. Pendekatan yang tepat dimulai dari kebutuhan yang sempit, batas izin yang jelas, dan kontrak perilaku yang dapat diuji. Tampilan serta implementasinya kemudian dibuat sendiri.

Panduan ini hanya untuk aplikasi milik sendiri, pekerjaan dengan izin eksplisit, atau perilaku generik yang boleh diemulasi. Jangan menyalin kode, aset, ikon, copy antarmuka, atau font proprietary. Jangan menyamar sebagai merek lain. Jangan membypass lisensi, subscription, DRM, atau kontrol akses. Bila kewenangan observasi maupun hak suatu materi tidak jelas, hentikan bagian tersebut sampai ada keputusan pemilik hak. Ini prosedur kerja konservatif, bukan penetapan bahwa semua bentuk reproduksi otomatis sah dalam setiap yurisdiksi.

Hasilnya adalah Ruang Abu, browser image tool original dengan satu vertical slice: import gambar lokal, grayscale, reset ke asli, dan export PNG. Lab berjalan offline dengan HTML, CSS, serta JavaScript native. Tidak ada model AI, instalasi paket, unggahan, atau klaim kesetaraan dengan editor komersial. Gambar kerja disediakan pengguna, bukan aset baru yang dibundel.

1. Pahami konteks, jangan mewarisi klaim

Intake lokal merekam sebuah video yang menampilkan launcher, sejumlah aplikasi, dan perbandingan kategori produk. Rekaman itu tidak membuktikan seluruh workflow selesai, fidelity format, atau kesiapan produksi. Transkrip ujaran tidak tersedia; karena itu tidak ada kutipan percakapan atau transkrip buatan dalam panduan ini.

ArtCraft relevan hanya sebagai konteks kematangan. Catatan review menyebut label Early alpha dan In development pada suite yang ditinjau. Snapshot GitHub yang tersedia hanya berisi tiga repository: storytold/artcraft, storytold/effectcraft, dan storytold/cadcraft. README EffectCraft dalam snapshot kosong. Bukti terbatas tersebut tidak menjadi audit semua aplikasi, bukti clean-room, atau bukti asal pembangunan menggunakan Opus. Cerita model dari unggahan sosial tidak diteruskan menjadi provenance resmi.

Pelajaran tekniknya sederhana: aplikasi yang bisa dibuka belum tentu mampu menyelesaikan pekerjaan. UI ekspor bukan bukti berkas ekspor valid. Lisensi source juga bukan izin menyeluruh untuk nama, logo, font, dan aset. Snapshot CADCraft membedakan lisensi kode, atribusi aset, serta ketentuan branding. Lab ini tidak mengambil implementasi ataupun materi visual dari repository tersebut.

2. Pisahkan observasi dari implementasi

Observasi menjawab apa yang pengguna lakukan dan hasil apa yang dibutuhkan. Implementasi menjawab bagaimana aplikasi baru menghasilkan hasil itu. Catatan observasi yang baik berbunyi: pengguna memilih berkas, melihat pratinjau, menerapkan grayscale, kembali ke gambar awal, lalu meminta PNG. Catatan buruk menyertakan salinan source, screenshot untuk dijiplak, teks tombol proprietary, atau ukuran panel yang sengaja dicocokkan dengan produk tertentu.

Untuk organisasi, simpan register izin berisi target, pemilik, pemberi izin, tanggal, ruang lingkup, dan larangan. Tim observasi menyusun spesifikasi netral; tim implementasi menerima spesifikasi tersebut, bukan materi internal target. Pisahkan akses repository dan arsip bukti bila pemisahan personel diperlukan. Catat keputusan desain sendiri beserta asal setiap materi yang masuk. Jangan menganggap proses terpisah menggantikan pemeriksaan hak.

Lab ini bukan sertifikasi proses clean-room terpisah secara personel. Ia contoh implementasi mandiri dari kebutuhan generik. Tidak dilakukan dekompilasi, pengambilan source pembanding, penyalinan interface, atau pengujian lisensi target. Jika organisasi mensyaratkan provenance formal, tambahkan audit akses dan review izin sebelum memakai istilah clean-room sebagai jaminan kepada pelanggan.

Spesifikasi netral untuk slice ini:

  • Masukan berupa PNG, JPEG, atau WebP lokal yang dikuasai pengguna.
  • Pengolahan hanya mengenai piksel di memori browser, tanpa menulis berkas asal.
  • Grayscale mengubah RGB, mempertahankan alpha, dan tidak menumpuk efek.
  • Reset mengembalikan snapshot import terakhir yang berhasil.
  • Export membuat PNG dari pratinjau saat ini, bukan menjamin fidelity metadata.
  • Kesalahan harus terbaca dan memberi langkah pemulihan, bukan layar kosong.

Sebelum observasi target nyata, tulis lembar kerja singkat: siapa pemilik aplikasi, fitur yang diizinkan diamati, perangkat sasaran, format masukan, dan bukti izin. Untuk contoh ini, targetnya bukan produk vendor tertentu: kebutuhan generik pengolahan gambar menjadi spesifikasi langsung. Tidak diperlukan kredensial, installer pembanding, ataupun akses layanan berbayar. Jika kelak target berubah, keputusan izin harus diperiksa ulang; keberhasilan lab tidak memperluas hak observasi secara otomatis.

3. Rancang alur kecil yang benar-benar selesai

Diagram berikut sengaja vertikal supaya tetap terbaca di layar kecil. Jalur gagal tidak mengganti snapshot asli yang sudah tersedia.

flowchart TD
  A[Pilih berkas lokal] --> B{Validasi dan decode}
  B -->|Gagal| C[Status dan coba lagi]
  B -->|Lolos| D[Simpan piksel asli]
  D --> E[Pratinjau]
  E --> F[Grayscale]
  F --> E
  E --> G[Reset ke asli]
  G --> E
  E --> H[Export PNG]

Keadaan awal menonaktifkan tombol pengolahan. Selama import atau encoding, input dan tombol dinonaktifkan agar operasi tidak saling mendahului. Setelah import berhasil, snapshot ImageData asli menjadi titik pemulihan. Grayscale selalu bekerja pada salinan snapshot tersebut. Pengguna tidak perlu memahami riwayat operasi atau mempertanyakan apakah dua klik mengubah hasil dua kali.

Jika import berikutnya gagal, aplikasi memulihkan gambar sebelumnya ke asli, bukan mempertahankan grayscale sebelumnya. Ini kompromi prototype yang dinyatakan secara terbuka. Perilaku tersebut menghindari kebutuhan snapshot tambahan dan memastikan ada titik pemulihan sederhana. Bila kebutuhan produk menuntut keadaan edit terakhir tetap persis, tambahkan snapshot keadaan aktif dan tes transaksi import sebelum memperluas fitur lain.

4. Jalankan lab tanpa dependency

Jalankan lab Ruang Abu di browser, atau unduh lab ZIP untuk penggunaan offline. Ekstrak ZIP, lalu buka clean-room-image-tool/index.html langsung melalui browser modern. JavaScript memakai script biasa, bukan module, sehingga tidak membutuhkan server development atau unduhan paket. Putuskan koneksi internet untuk pemeriksaan offline manual. Node diperlukan hanya saat menjalankan tes.

cd clean-room-image-tool
node test.mjs

Gunakan gambar buatan sendiri atau gambar yang hak penggunaannya jelas. Pilih berkas, tekan Grayscale, lalu Reset ke asli. Terapkan kembali Grayscale dan tekan Unduh PNG. Periksa folder unduhan browser, buka PNG hasilnya, dan bandingkan dimensi serta tampilannya. Nama hasil tetap ruang-abu.png; browser dapat menambah sufiks ketika nama sudah ada. Jangan mengartikan pesan persiapan PNG sebagai konfirmasi bahwa sistem operasi sudah menyimpan berkas.

index.html memuat UI, CSS, label, status, dan kebijakan pembatas koneksi. app.js memuat validasi serta pengolahan. test.mjs menggunakan Node stdlib, sementara README.md menjelaskan langkah dan batas lab. Tidak ada cover, ilustrasi, sample image, atau font baru. Tipografi memakai font lokal OS; desain menggunakan latar lembut, tombol hijau, dan urutan kerja sederhana yang tidak meniru panel produk pembanding.

5. Kode penting dan batas input

Allowlist MIME diterapkan sebelum decode. Ukuran berkas dibatasi 10 MiB. Setelah decode, jumlah piksel maksimal 16 juta dan panjang sisi maksimal 8192 piksel. SVG tidak diterima; lab tidak memerlukan konten vektor atau sumber daya bersarang. Nilai MIME bukan bukti isi yang terpercaya, sehingga decode tetap harus berhasil. Berkas berekstensi PNG tetapi isinya rusak tidak boleh dianggap valid hanya karena nama atau type-nya.

validateFile(file);
objectUrl = URL.createObjectURL(file);
const image = new Image();
image.src = objectUrl;
await image.decode();
validateDimensions(image.naturalWidth, image.naturalHeight);

Batas dimensi baru diketahui setelah decode. Artinya, lab belum sepenuhnya menangkal gambar terkompresi kecil dengan kebutuhan memori decode sangat besar. Untuk produksi, diperlukan strategi pemeriksaan header, pembatasan sumber daya, atau isolasi decode yang diuji pada format yang didukung. Jangan menyebut allowlist ini sebagai sanitizer universal.

Grayscale memakai bobot kanal berikut. Kanal alpha tidak disentuh.

const gray = Math.round(
  0.2126 * pixels[offset] +
  0.7152 * pixels[offset + 1] +
  0.0722 * pixels[offset + 2]
);
pixels[offset] = pixels[offset + 1] = pixels[offset + 2] = gray;

Ini pendekatan berbobot pada nilai kanal sRGB langsung, bukan kalkulasi luminansi linear atau pipeline color-managed. Lab cocok untuk demonstrasi efek visual, bukan proofing cetak atau evaluasi warna presisi. Transparansi tetap ada, tetapi metadata, profil warna, dan animasi tidak dijanjikan bertahan. Gambar animasi hanya dipakai sebagai gambar statis frame pertama sesuai batas lab.

Reset memakai context.putImageData(original, 0, 0). Export memakai canvas.toBlob dengan MIME image/png, lalu tautan download sementara. Object URL input dilepas setelah import selesai. URL unduhan dilepas setelah jeda 60 detik untuk memberi browser waktu mengaksesnya. Tidak ada data yang dipersistenkan; tutup tab berarti keadaan hilang.

6. Acceptance matrix

Kolom bukti membedakan yang benar-benar dijalankan dari pekerjaan verifikasi yang masih diperlukan. Pemeriksaan source memastikan kontrak tertentu tersedia, bukan membuktikan keseluruhan perilaku browser.

Untuk pengujian manual, siapkan gambar kecil buatan sendiri dengan bidang merah, hijau, biru, serta area transparan. Catat dimensi awal dan simpan salinan terpisah. Tambahkan berkas kosong dan berkas rusak dengan MIME yang diterima. Rekam nama browser, versi, OS, langkah, hasil yang diharapkan, serta hasil aktual. Fixture ini rencana pengujian, bukan aset yang dibundel atau bukti bahwa pemeriksaan browser sudah dilakukan.

Kasus Hasil yang diterima Bukti atau metode
Halaman awal Tombol edit tidak aktif; petunjuk input terbaca Kontrak elemen dites; interaksi manual belum
PNG/JPEG/WebP valid Pratinjau berdimensi benar dan tombol aktif Allowlist dites; decode nyata manual belum
MIME lain Ditolak dengan pesan format Fungsi validasi dites
Berkas kosong atau di atas 10 MiB Ditolak sebelum decode Nilai batas dites
Sisi atau piksel berlebih Ditolak setelah decode Fungsi dimensi dites
Isi gambar rusak Pesan decode gagal; pengguna bisa memilih lagi Jalur source diperiksa; browser manual belum
Grayscale RGB sama, alpha tetap Nilai merah, hijau, biru dites
Klik grayscale berulang Hasil stabil, tidak menumpuk perubahan Fungsi idempoten dites; klik manual belum
Reset Piksel asli dikembalikan Kontrak handler dites; visual manual belum
Import gagal setelah edit Gambar sebelumnya kembali ke asli Review jalur kode; browser manual belum
Export PNG pratinjau disiapkan; sumber tidak ditimpa Kontrak MIME/nama dites; unduhan manual belum
Keyboard dan mobile Fokus terlihat; label/status tersedia; tombol membungkus Kontrak markup/CSS dites; AT manual belum
Offline Tidak ada dependensi atau request jaringan aplikasi Kontrak source dites; panel Network manual belum

7. Aksesibilitas bukan fitur tambahan

Input memiliki label eksplisit dan petunjuk batas yang dihubungkan melalui aria-describedby. Semua aksi memakai tombol native sehingga pengguna keyboard mendapat perilaku standar. Fokus terlihat melalui :focus-visible. Status memakai role="status", aria-live="polite", serta aria-atomic="true". Perubahan status tidak sengaja merebut fokus pengguna.

Canvas mempunyai nama aksesibel yang berubah setelah import, grayscale, dan reset. Nama itu menjelaskan keadaan, bukan mengklaim mendeskripsikan seluruh isi gambar. Untuk kebutuhan pengguna nonvisual yang lebih luas, perlu desain alternatif dan riset pengguna. Prototype belum menawarkan deskripsi semantik otomatis. Jangan menyebut keberadaan atribut ARIA sebagai sertifikasi aksesibilitas.

Pemeriksaan manual wajib mencakup Tab dan Shift+Tab, aktivasi tombol dengan keyboard, zoom 200 persen, layar selebar 320 piksel, dan pembaca layar pada platform sasaran. Pastikan tombol nonaktif tidak menimbulkan kebuntuan ketika import gagal. Periksa pula kontras teks, status panjang, dialog pemilih berkas, serta perilaku fokus setelah download. Semua pemeriksaan itu masih terbuka sampai dilakukan di browser nyata.

8. Threat dan IP checklist

Gunakan checklist ini sebelum demo dipublikasikan atau source diserahkan. Keamanan mencakup input tidak terpercaya, sedangkan hak mencakup asal materi dan wewenang penggunaan.

  • Ruang lingkup pekerjaan termasuk milik sendiri, izin eksplisit, atau perilaku generik yang telah disetujui.
  • Tidak ada source, aset, ikon, copy, font proprietary, maupun screenshot target yang digunakan sebagai bahan salinan.
  • Nama dan tampilan tidak menimbulkan kesan afiliasi, endorsement, atau produk resmi vendor lain.
  • Tidak ada bypass lisensi, subscription, DRM, autentikasi, atau akses berbayar.
  • Gambar uji mempunyai asal dan hak yang tercatat; tidak menyertakan data pribadi tanpa persetujuan.
  • Allowlist, batas byte, batas dimensi, dan kegagalan decode diuji, termasuk input rusak.
  • Tidak ada analytics, CDN, request upload, atau telemetry; kebijakan koneksi melarang koneksi aplikasi.
  • Teks status memakai textContent, bukan HTML dari input pengguna.
  • URL sementara dibersihkan; export tidak menulis ulang berkas sumber.
  • Risiko memori setelah decode serta keterbatasan privasi lingkungan browser dijelaskan.

Offline tidak berarti kebal semua kebocoran. Ekstensi browser, malware perangkat, screenshot, dan kebijakan perangkat perusahaan berada di luar kontrol lab. Kebijakan CSP membatasi aplikasi, bukan mengendalikan komponen tersebut. Hindari gambar sensitif di perangkat yang tidak dipercaya dan jangan menyatakan lab telah diaudit keamanan menyeluruh.

9. Error dan failure recovery

Kesalahan import menyebut tindakan berikutnya: gunakan format yang didukung, kecilkan gambar, atau pilih berkas lain. Input direset setelah selesai sehingga berkas yang sama bisa dipilih ulang. URL input dibersihkan melalui finally. Snapshot sebelumnya dipulihkan ke asli bila tersedia. Berkas sumber tetap berada di disk tanpa penulisan ulang.

Jika canvas tidak tersedia, aplikasi memberi pesan dan menonaktifkan input. Jika pengolahan gagal, snapshot asli tetap menjadi titik pemulihan. Jika encoder PNG menghasilkan null atau operasi export melempar error, status menyatakan kegagalan dan tombol kembali tersedia. Penolakan dialog unduhan atau lokasi penyimpanan oleh browser tidak bisa dikonfirmasi secara andal melalui tautan download; pengguna harus memeriksa hasilnya sendiri.

Memori adalah kegagalan penting: staging canvas, snapshot, buffer grayscale, dan encoder dapat hidup bersamaan. Batas piksel mengurangi risiko tetapi bukan jaminan pada ponsel bermemori kecil. Browser yang menutup tab akibat kehabisan memori dapat menggagalkan recovery JavaScript. Karena tidak ada autosave, pengguna harus mengimpor ulang. Pernyataan batas ini lebih jujur daripada menjanjikan pemulihan semua error.

10. Bukti eksekusi lab

Pada 13 Oktober 2026, perintah berikut benar-benar dijalankan dari root workspace:

node lab/clean-room-image-tool/test.mjs

Output nyata:

PASS: 29 checks (source contracts + pure functions; no browser E2E)

Tes memakai node:assert/strict, node:fs, dan node:vm. Ia memeriksa enam elemen UI, bahasa, label/status, indikator fokus/mobile, larangan koneksi, jalur decode/validasi, kontrak export, pelepasan URL, reset, snapshot asli, serta instruksi README. Fungsi validasi dan grayscale benar-benar dieksekusi dalam VM dengan stub DOM minimum.

Assert akan menghentikan proses dengan kegagalan bila kontrak yang diperiksa hilang atau hasil fungsi berubah. Ini lebih kuat daripada mencetak pesan sukses tanpa pemeriksaan. Namun pencarian pola source tidak membuktikan tidak adanya semua kemungkinan jaringan, dan stub DOM tidak menjalankan decoder, layout, canvas, atau download browser. Tidak ada browser E2E, audit pembaca layar, atau verifikasi PNG unduhan yang dijalankan. Baris acceptance manual tidak boleh ditandai selesai berdasarkan hasil Node ini.

11. Kriteria selesai dan jalan produksi

Draft lab selesai ketika empat file tersedia, tes Node lulus, panduan memuat hasil nyata, dan batas pengujian dinyatakan. Itu kriteria deliverable prototype, bukan kriteria peluncuran produk. Sebelum demo pengguna dianggap diterima, seluruh baris manual pada acceptance matrix harus menghasilkan catatan browser, OS, input, langkah, hasil, dan isu tersisa.

Untuk produksi, kerjakan urutan berikut:

  1. Selesaikan review hak, inventaris materi, dan lisensi redistribusi. Kode lab belum diberi lisensi distribusi oleh pemilik proyek; jangan mengiklankannya sebagai MIT atau Apache. Tidak ada dependency eksternal maupun aset pihak ketiga yang dibundel. Font lokal tetap mengikuti lisensi OS.
  2. Uji browser sasaran dengan fixture gambar buatan sendiri: alpha, orientasi foto, berkas rusak, batas dimensi, dan variasi warna. Simpan hasil export lalu periksa dimensi serta pikselnya.
  3. Tambahkan pengujian browser untuk interaksi, pembatalan, kegagalan decode, reset, dan download. Pisahkan hasil otomatis dari pemeriksaan manual aksesibilitas.
  4. Tetapkan anggaran memori dan latensi di perangkat minimum. Jika angka tidak terpenuhi, pertimbangkan pembatasan dimensi lebih rendah atau worker, bukan langsung menambah framework.
  5. Putuskan kontrak format dan warna: ICC, EXIF/orientasi, metadata, serta animasi. Implementasikan hanya yang dibutuhkan pengguna, lalu tambah fixture regresi.
  6. Siapkan distribusi dengan header keamanan yang diuji, versioning, changelog, pelaporan masalah, dan prosedur rollback. Jika hosting dipilih, dokumentasikan log server serta konsekuensi privasi yang berbeda dari membuka file lokal.

Layer, RAW, PSD, plugin, batch processing, kolaborasi, dan undo bertingkat sengaja tidak ada. Tambahkan hanya setelah satu alur kecil telah terbukti berguna dan stabil. Ukuran keberhasilan bukan seberapa mirip layar dengan produk terkenal, melainkan apakah pengguna dapat menyelesaikan kebutuhan yang disepakati tanpa kehilangan data, kebingungan, atau pelanggaran hak.

Sources

Panduan memakai sumber lokal berikut saja, tanpa browsing tambahan:

  • mission-clone.md: kontrak keluaran, frontmatter, cakupan vertical slice, batas hak, dan kewajiban bukti eksekusi.
  • inputs/intake.md: cakupan rekaman, keterbatasan transkrip, konteks klaim sosial, serta rancangan reproduksi berizin.
  • inputs/codex-file-review.md: pemisahan fakta dan klaim, kematangan aplikasi, batas audit runtime, serta caveat lisensi.
  • inputs/official-github-evidence.json: snapshot tiga repository dan README ArtCraft/CADCraft; tidak dianggap bukti provenance model atau audit seluruh suite.
  • lab/clean-room-image-tool/index.html, lab/clean-room-image-tool/app.js, lab/clean-room-image-tool/test.mjs, dan lab/clean-room-image-tool/README.md: implementasi lab, kontrak yang dites, dan output eksekusi yang dicatat dalam panduan ini.
More Toolkits & Guides
Based in Jakarta
Digital Business research and collaboration

Let's build it as one system.