Imported from tri-evendi/sai-accounting (
AGENTS.md). Install upstream withnpx skills add tri-evendi/sai-accounting. Copyright stays with the author.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
UI/UX & Design System (WAJIB untuk pekerjaan tampilan)
Setiap kali membuat/mengubah/mereview UI (halaman, komponen, warna, tipografi, layout, chart), ikuti proses ini:
-
Baca sumber kebenaran desain dulu:
design-system/sai-accounting/MASTER.md. Jika adadesign-system/sai-accounting/pages/<page>.md, aturannya meng-override MASTER. -
Gunakan skill
ui-ux-pro-maxuntuk rekomendasi berbasis data (style/palet/tipografi/aksesibilitas/chart) & panduan stack:python3 .claude/skills/ui-ux-pro-max/scripts/search.py "<query>" --domain <ux|color|typography|chart> --stack nextjsSkill terkait juga tersedia:
design-system(token). Skillui-stylingsudah DIHAPUS dari repo ini: isinya shadcn/Tailwind, dan keduanya dicabut di issue #203 — jangan ditambahkan kembali. -
Patuhi prinsip app ini: simple surface, standard engine — ramah pengguna awam, tapi proses akuntansi tetap baku. Light-first; semantik warna uang (hijau masuk / merah keluar) tak boleh warna-saja; angka
tabular-numsrata-kanan formatid-ID. -
Reuse komponen
src/components/ui(Ant Design v6) & ikon@ant-design/icons(satu paket ikon saja; ukuran lewatstyle={{ fontSize }}, bukan propsize/width/height—size={16}LOLOStsclalu mendarat sebagai atribut DOM yang tak mengatur apa pun; lihat "Ikon" di MASTER.md). TANPA Tailwind dan tanpaclassNamesejak issue #203: gaya ditulis SEBARIS (style={{...}}), warnanyavar(--ant-...)atautheme.useToken(), dan nilai warna mentah (hex,rgb(), nama warna CSS) tidak ditulis di luarsrc/lib/theme/antd-tokens.ts— dijaga ESLintsai/warna-token-antd(#204). Sebuah kelas tidak akan gagal - tidak ada lembar gaya yang memaknainya, jadi ia hanya berhenti berlaku. Yang tak punya bentuk sebaris (:hover,::after,@media) hidup di satu<style href precedence>di komponennya, menyasar atributdata-*(polalanding-scale.ts/ui/table.tsx). Form:react-hook-form+zodvia polaForm(lihat "Konvensi Form" MASTER.md). Tabel:StaticTable(bawaan - dirender server, tanpa JS) atauDataTable(AntD, client, +80 KB gzip per rute — hanya bila memang butuh sortir/filter seketika); nominal lewatMoney/MoneyInput. Tombol yang menuju ke suatu tempat:<ButtonLink href>untuk rute di dalam app (satu<a class="ant-btn">+ navigasi sisi-klien + prefetch, #289) dan<Button href>untuk tautan keluar /download/ pemuatan penuh yang disengaja. Jangan<Link><Button/></Link>— dua elemen interaktif bersarang, ditolaktests/anchor-button-nesting.test.ts;asChildsudah dicabut di #250 (tidak aman dari server component) dantests/button-no-aschild.test.tsmenolaknya kembali. -
Sebelum menyerahkan UI, lewati Pre-Delivery Checklist di MASTER.md. Gerbangnya dua:
bun run verify(typecheck + lint + vitest; jangannpm, janganbun test) danbun run buildyang harusEXIT=0— verify hijau TIDAK membuktikan aplikasinya bisa dibangun, dan itu sudah terjadi sekali. Aturan mana dijaga penjaga yang mana: §Penjaga di MASTER.md.⚠ Siapa yang menjalankan
bun run build. Gerbangnya tetap DUA — yang berubah hanya siapa yang menjalankan yang kedua. Agent latar / sesi cabang: JANGAN jalankanbun run build. Gerbang Andabun run verifysaja, dan ketiadaan build ditulis apa adanya di badan PR ("bun run buildtidak dijalankan — dijalankan sesi utama di atas hasil gabungan"), bukan didiamkan: PR yang tiba-tiba menyebut satu gerbang akan terbaca sebagai kelalaian oleh orang berikutnya.Sebabnya mesin, bukan doktrin: kotak ini ~3,6 GB RAM dengan produksi hidup di atasnya,
next build~10 menit, dan dua agent yang membangun bersamaan sudah menghasilkan OOM (exit 137) — kegagalan yang terbaca seperti kode rusak padahal bukan. Tiga pengukuran lain di sesi yang sama juga terbuang jadi timeout karena beban, bukan karena ada yang salah.Sesi utama tetap WAJIB menjalankannya, sekali, di atas
develophasil gabungan — bukan di cabang mana pun. Itu justru lebih kuat daripada build per-cabang: satu-satunya build yang pernah gagal di repo ini gagal di hasil gabungan, sementara setiap cabangnya hijau sendiri-sendiri. Menghapus langkah ini berarti mempromosikan sesuatu yang belum pernah dibangun.
Otorisasi / RBAC (WAJIB untuk halaman & API route baru)
Otorisasi berbasis izin terpusat — lihat docs/RBAC.md. Inti: matriks izin di src/lib/authz.ts; halaman memanggil requirePagePermission("resource.action"), API requireApiPermission(...), tampilan can(...). Jangan membandingkan string peran atau menulis daftar ["managing_director","finance_manager"] di luar matriks — tes authz-coverage menolak halaman/route tanpa deklarasi izin. Sejak issue #73 matriks di kode adalah BAWAAN: matriks EFEKTIF = bawaan + override DB (role_permission_overrides) yang dikelola peran berakses penuh di halaman /permissions; penjaga memakai canEffective (src/lib/authz-effective.ts), jadi jangan tanam asumsi "peran X pasti tidak bisa Y" di luar penjaga.
Multi-perusahaan (WAJIB dibaca sebelum menyentuh basis data)
Sejak issue #104 buku besar setiap PT hidup di basis data sendiri; pengguna,
daftar perusahaan, dan keanggotaan ada di basis data kendali. Lihat
docs/MULTI-COMPANY.md. Aturan yang tidak boleh dilanggar: konteks perusahaan
yang hilang harus MELEMPAR, tidak pernah jatuh ke basis data bawaan — jatuh ke
bawaan berarti transaksi PT A tertulis ke buku PT B tanpa galat dan tanpa jejak.
Halaman & route mendapat konteksnya dari penjaga; skrip/cron wajib
runWithCompany(). Cache tingkat modul yang isinya milik satu perusahaan
wajib dikunci per companyId. Jangan pernah membuat FK ke users dari basis
data perusahaan — pakai id global + users-directory.ts.
Database & Skema (WAJIB untuk perubahan data)
Setiap perubahan model Prisma / migration / tabel wajib mengikuti docs/DATABASE.md. Inti:
- Inggris ·
snake_casedi DB (via@map) · tabel jamak (@@map) · Prisma camelCase. - Setiap tabel:
id(Int autoincrement) +created_at+updated_at; master data +is_active(nonaktif, bukan hard-delete yang direferensikan). - Uang =
Decimal(15,2), kuantitasDecimal(15,3), kursDecimal(18,6)— JANGAN Float/Int. - Valas simpan
currency+rate+base_amount(IDR). - Enum-like =
String @db.VarChar+z.enum(nilaisnake_case);@uniqueuntuk code/number;@@indexuntuk FK/date/status. - Mesinnya PostgreSQL sejak 15 Okt 2026. Migration ditulis tangan di
prisma/postgresql/<company|control|platform>/NNNN_<nama>/migration.sql(dialek PostgreSQL), diterapkanbun run db:migrate:all(migrate deploy); jalankanbun run db:generatesetelahnya.prisma/migrations/danprisma/{control,platform}/migrations/adalah ARSIP MariaDB hanya-baca: migration yang ditulis di sana tidak akan pernah diterapkan. - Lewati Checklist tabel baru di
docs/DATABASE.mdsebelum commit.
