Imported from mcfuryamen/kasol (
kaki5/AGENTS.md). Install upstream withnpx skills add mcfuryamen/kasol --skill kaki5. Copyright stays with the author.
AGENTS โ Kasir Solo Kaki Lima (kaki5)
Konteks spesifik aplikasi kaki5 (POS pedagang kaki lima).
Selalu baca ../CONTEXT.md untuk standar ekosistem โ file itu atasan,
dokumen ini bawahan. Untuk detail teknis mendalam: docs/DEVELOPER.md.
Peran khusus:
CONTEXT.md:71menetapkan kaki5 = REFERENSI ARSITEKTUR aplikasi klien (pola kode, sync profil, offline-first). App klien lain meniru kaki5. Kesalahan yang dibiarkan di sini akan menular ke aplikasi lain.
๐ Info Aplikasi
| Item | Value | Bukti |
|---|---|---|
| Folder | kaki5/ |
โ |
| Port dev server (RESMI, jangan diubah) | 8086 (bind 127.0.0.1 saja) |
../CONTEXT.md:51, server.cjs:9,46 |
APP_VERSION |
1.0.109 |
js/version.js:7 |
CACHE_BUST / SW |
v184 |
js/version.js:18, sw.js:201 |
| Prefix produk | KK5 |
js/license.sync.js:14 |
| Salt | KASIRSOLO-KAKI5-HMAC-V2 โ satu-sumber efektif sejak hardening 2026-09-14: kolom cloud products.salt tidak lagi terbaca anon (revoke per-kolom; ../rosok/docs/supabase-hardening-2026-09-14.sql). โ ๏ธ Rotasi = dua langkah sadar: update klien+server DULU baru ganti kolom |
js/license.logic.js:157 |
APP_TYPE (cloud) |
kaki5 |
js/sync.js:31 |
| Database Dexie | KasirSoloKakiLima, skema v8, 9 object store |
js/db.js:6,137 |
manifest.json |
name Kasir Solo - Kaki Lima, short_name KasirKaki5 |
manifest.json |
| Vercel project | kasir-kaki5 (base path kaki5/) |
../DEPLOYMENT.md:88 |
| Domain LIVE | kaki5.kasirsolo.com |
../DEPLOYMENT.md:168 |
| Repo BETA / LIVE | mcfuryamen/kasol-beta โ <app>.vercel.app ยท mcfuryamen/kasol โ custom domain |
../DEPLOYMENT.md:178-179 |
๐๏ธ Struktur File
kaki5/
โโโ index.html # 1018 baris: 6 halaman .page + 21 overlay `.modal-overlay` + CSP meta (:16)
โโโ css/style.css # SATU-SATUNYA stylesheet (dijaga test-css-drift.js)
โโโ js/ # 45 file .js โ lihat peta modul di docs/DEVELOPER.md ยง3
โ โโโ app.js # entry: wire window + dispatcher data-action + boot()
โ โโโ app-state.js # satu-satunya holder state (binding read-only + setter)
โ โโโ db.js # Dexie v1..v8 + getSetting/setSetting
โ โโโ *.logic.js # lapisan murni: tanpa DOM/DB (uji unit tanpa browser)
โ โโโ *.ui.js # lapisan DOM: tanpa akses DB
โ โโโ *.sync.js # lapisan cloud
โ โโโ settings.js # FACADE (re-export) โ bukan implementasi
โ โโโ license.js # FACADE (re-export)
โ โโโ pos.js # FACADE + orkestrasi
โ โโโ supabase.min.js # vendor (harus di-track git)
โโโ api/supabase-config.js # serverless: suntik URL/anon-key
โโโ assets/ # 8 ukuran ikon + region/provinces.json
โโโ docs/ # DEVELOPER.md ยท REGRESSION-CHECKLIST.md
โโโ sw.js # Service Worker, 3 strategi (lihat ยง Konvensi 7)
โโโ server.cjs # dev server 8086 โ DI-GITIGNORE, tidak ikut rilis
โโโ test-*.js # harness QA โ DI-GITIGNORE (.gitignore:112)
โโโ DESIGN.md ยท CHANGELOG.md ยท README.md ยท AGENTS.md
โโโ vercel.json ยท manifest.json ยท package.json ยท .vercelignore
โ ๏ธ Konvensi WAJIB (pelanggaran = bug nyata, bukan gaya)
-
DILARANG inline handler. CSP
script-src 'self'(index.html:16) menolak<script>inline, danindex.htmlsekarang 0 atributonclick/onchange. Semua interaksi lewat atributdata-action="nama-aksi"+case 'nama-aksi'dihandleDataAction()(js/app.js:333). Dispatcher dipanggil 4 listener delegasi:click(:967),keydownEnter/Space (:997),input(:1019),change(:1020).input/changewajib karenadata-actiondi<input>/<select>tak pernah memicuclick. -
Modal gerbang = satu daftar gate. Overlay yang tidak boleh ditutup dari UI didaftarkan SEKALI di
HARD_GATE_OVERLAYS(js/modal.js:48):lockOverlay(revoke admin) danupdateOverlay(force update). Listener Escape,closeAllModals(), klik backdrop/navbar (app.js:974,978), dannavigation.js:69semuanya menyapu daftar yang sama. Menambah jalur tutup denganexcept:sendiri = gerbang bisa dilewati diam-diam (persis bug yang diperbaiki v170). Sejak v181bukaKasModalBUKAN lagi anggota daftar ini โ gerbang kas hanya mengunci halaman Jualan (watcherkas.js:168-184menegakkan ulang; Escape/backdrop/navigasi bebas menutup). Modal gerbang lisensi tetap: tidak ada tombol batal, dan input wajib kosong ditolak (kosong โ 0). -
JEBAKAN FACADE + WIRE-MAP (akar bug v166).
app.jsmengisiwindow[key]dari modul yang ia import sendiri, dengan guard:if (modKey !== '__wired' && m[modKey] !== undefined) window[key] = m[modKey];(
app.js:72,81,91,101,111,121,132,142). Kalau nama tidak di-export modul target, guard lolos DIAM-DIAM tanpa error โwindow.fnundefinedโ fitur mati total tanpa jejak di konsol. Karena itu: setiap nama di_*WireMapwajib ada di daftar re-export file facade yang di-importapp.js(settings.js,pos.js,license.js).settings.js= facade,settings.ui.js= implementasi. Harness QA yang mengimporsettings.ui.jslangsung tidak akan menangkap lubang ini. -
escapeHtml/buildSafeHtmluntuk SEMUA nilai dinamis yang masuk HTML. Nilai dari user (nama menu, catatan, nama usaha) tidak pernah boleh ditempel mentah. -
Rilis = bump 6 slot sinkron (lihat
docs/REGRESSION-CHECKLIST.mdยง3):APP_VERSION,CACHE_BUST,version.json.version,version.json.cacheBust,sw.js CACHE_NAME,index.html ?v=. Salah satu tertinggal โ overlay update tidak muncul (js/update.js:79bail bilaremote.cacheBust === CACHE_BUST) dan cache SW tidak invalid. Insiden tercatat:CHANGELOG.md:327. -
app-state.jsread-only. Mutasi state hanya lewat setter yang diekspor modul itu; jangan menulis properti binding state langsung dari modul fitur. -
Migrasi DB bersifat aditif โ DILARANG drop tabel/kolom.
db.version(N)hanya boleh menambah store/index. Tabelkaslama sengaja tidak di-drop walau isinya sudah dimigrasi kepengeluaranolehdb.version(8).upgrade()(js/db.js:124-127,147-174). Tabelpengaturanjuga legacy dan tidak dibaca kode lagi, tapi tetap dipertahankan. -
SW punya 3 strategi, bukan satu.
/supabase.coโ network-only (sw.js:281); HTML โ cache-first supaya bisa navigasi offline (sw.js:292); aset statis โ network-first dengan fallback cache (sw.js:312). Jangan tulis "network-first" saja di dokumen โ itu salah dan sudah sempat menyesatkan. -
Cloud = sumber kebenaran untuk lisensi & profil (
../CONTEXT.md:87-101), tapi offline-first: gagal jaringan tidak boleh mengubah/menghapus state lokal.ensureSynced()push otomatis bersifat backfill-only; menimpa cloud hanya lewatforce(form profil / tombol sinkron / retry pending). -
Keputusan pemilik soal gerbang lisensi (2026-08-29): kuota transaksi habis TIDAK mengunci aplikasi โ hanya banner
#quotaBanner+ blokir transaksi (js/app.js:260-276,js/pos.js:566-573). Yang boleh full-lock hanya revoke admin, lewatlockOverlay(js/license.ui.js:178). Jangan "memperbaiki" ini. -
Fitur kas bisa dimatikan user. Gerbang
fiturKasAktif()ada dijs/kas.js:136, 158, 231, 286, 342, 468,js/pos.js:409(buka tab Jualan โ munculkan modal Buka Kas, v169), danjs/pos.js:545(guardsimpanPenjualan). Saat mati, kios boleh jualan tanpa buka kas. Jangan pernah menghapus bariskasShiftuser saat mematikan fitur; shift yang masih terbuka harus bisa ditutup setelah fitur nyala lagi. Dua aturan yang menjaga gerbang ini tetap jujur (bug 2026-09-04: kios bisa jualan tanpa buka kas padahal Pengaturan menampilkan "aktif"): (a)fiturKasAktif()wajib membaca DB tiap dipanggil โ jangan kembalikan cache "baca sekali", karena IndexedDB dipakai bersama antar tab/jendela dan cache yang menyimpang membuat gerbang POS terbuka diam-diam; (b) saklar wajib disinkronkan dari DB di awalloadSettings(), sebelum panggilan cloud mana pun, karenaindex.htmlmen-hardcodechecked+ teks "transaksi diblok kalau kas belum dibuka" pada saklar itu โpullCloudProfileIfOnline()tidak punya timeout, jadi kalau menggantung tampilan tetap mengaku fitur AKTIF.
๐งช QA
Jalankan dari CWD kaki5 (test-html-refs.js memakai process.cwd()):
| Harness | Status baseline |
|---|---|
test-css-drift.js, test-db-migrations.js, test-dynamic-imports.js, test-imports.js, test-shim.js |
โ hijau |
test-data-actions.js, test-html-refs.js, test-modules.js |
โ merah sejak rilis 1.0.97 โ bukan regresi baru (dikonfirmasi ulang di v170 & v182: sinyal identik) |
Penyebab merah & daftar DELEGATED_OK/DEAD_OK dijelaskan di
docs/REGRESSION-CHECKLIST.md ยง5. Jangan memblokir rilis karena tiga harness itu,
tapi jangan juga menambah korban baru: bandingkan dulu dengan blob HEAD sebelum
menyimpulkan regresi.
๐ Rilis
๐ฆ ATURAN RILIS โ SELURUH EKOSISTEM KASOL (WAJIB, aturan pemilik 2026-09-06)
- Default = commit + rilis BETA saja (mirror
kasol-beta). Fix disetujui โ beta boleh langsung. - Rilis LIVE (mirror
kasolโ produksi) WAJIB perintah EKSPLISIT pemilik, PER RILIS. Approval "gas" atas fix BUKAN izin rilis live. - Jangan improve sendiri di luar permintaan โ temuan lain = SARAN, menunggu dipilih.
- Teks lengkap:
../CONTEXT.mdโ "๐ฏ Keputusan Strategis" โ "๐ฆ Aturan Rilis".
Alur 2-mirror (../DEPLOYMENT.md:127-181): folder kerja โ push-beta.ps1 โ mirror
kasol-beta โ GitHub BETA โ <app>.vercel.app. Stabil โ push-live.ps1 โ mirror
kasol โ kaki5.kasirsolo.com.
Catatan operasional yang terbukti di mesin ini:
- Kedua skrip selalu berhenti di
Read-Host(non-interaktif) setelah snapshot ter-commit dan branch di-renamemain. Push manual berikutnya itu jalur normal:git -C <mirror> -c http.postBuffer=524288000 -c http.lowSpeedLimit=1000 -c http.lowSpeedTime=60 push origin main --force-with-lease=main:<SHA_REMOTE_LAMA>(SHA lama diambil darigit ls-remotesebelum push โ lease polos tidak andal karena skrip menghapus branchmainlokal). - Bukti rilis = 5 jalur independen, bukan output git:
ls-remote,fetch+FETCH_HEAD, APIcurl.exe, isi file diraw.githubusercontent.com, dan konten yang benar-benar terhidang di domain-nya (/js/version.json,/sw.js,/).gh apirusak di mesin ini โ pakaicurl.exe -s --noproxy '*'. - URL BETA bukan dari field
homepagerepo.homepagekasol-betamenunjukkaki5beta.vercel.appyang 404 semua path; yang benarhttps://kq5beta.vercel.app(cekvercel project ls). Jangan fetch/index.htmldi Vercel โ ia 308 ke/. git add -ADILARANG. Stage file tracked saja:git add -u kaki5. Artefak_qa-*danrosok/*jangan sampai ikut.- Commit/push LIVE hanya atas perintah eksplisit pemilik (beta = default setelah fix disetujui โ lihat "๐ฆ ATURAN RILIS" di atas).
๐ Data user
Aplikasi ini dipakai untuk mencatat uang asli. Aturan kerja QA yang terbukti:
- Jangan reload/navigate tab aplikasi user saat keranjang terbuka (cart hanya di memori
localStorage['kaki5-cart']).
- Aksi
check/uncheckpada saklar di app asli menulis ke IndexedDB user โ siapkan rencana pemulihan sebelum mencoba. - Verifikasi state lewat dump read-only, bukan screenshot.
- Harness QA berdiri sendiri wajib meniru head
index.html:<script src="dexie.min.js">(db.js memakai globalDexie) danjs/dev-unregister-sw.js.
๐ Dokumen Terkait
| Dokumen | Isi |
|---|---|
README.md |
fitur & cara pakai, skema DB, arsitektur 3-layer |
docs/DEVELOPER.md |
peta 45 modul, boot sequence, lisensi, kas, cloud, QA |
docs/REGRESSION-CHECKLIST.md |
kelas bug berulang, aturan bump versi, baseline harness |
DESIGN.md |
model lisensi/kuota & kontrak cloud-nya |
CHANGELOG.md |
riwayat rilis per vNNN / 1.0.NN |
../CONTEXT.md |
standar ekosistem (port registry, lisensi hybrid, arah cloud) |
../DEPLOYMENT.md |
alur rilis 2-mirror, guard drift, domain |