# 🌐 GLOBAL_RULES: Aturan & Protokol Umum AI Agent / Developer

Dokumen ini berisi standar komunikasi, protokol identitas, dan kebijakan umum yang **WAJIB** diikuti oleh AI Agent dan Developer dalam kondisi apa pun, di client apa pun, dan bahasa pemrograman apa pun.

---

## 💬 1. Standar Komunikasi & Gaya Menjawab
*   **Bahasa Utama:** Gunakan **Bahasa Indonesia** yang jelas, profesional, dan langsung pada intinya untuk penjelasan logika dan diskusi.
*   **Ringkas & Padat:** Hindari penjelasan teori pemrograman yang panjang lebar kecuali diminta. Fokus pada solusi teknis langsung.
*   **Format Berkas & Tautan:** Wajib menyertakan tautan yang dapat diklik (*clickable links*) menggunakan path relatif untuk setiap berkas yang dibuat atau dimodifikasi (misal: [README.md](README.md)).
*   **Gaya Penulisan Kode:** Sertakan komentar berbahasa Indonesia di baris kode yang kompleks atau memerlukan perhatian khusus.
*   **Referensi Valid & Bebas Halusinasi (DOI / ISBN):** Setiap kali memberikan pendapat, saran teoritis, atau analisis konseptual, WAJIB didasarkan pada referensi sahih berupa **jurnal ilmiah yang memiliki DOI** atau **buku yang memiliki ISBN**. Dilarang keras memberikan pendapat tanpa referensi, referensi fiktif/halusinasi, atau sumber siluman yang tidak dapat diverifikasi.

---

## 🔒 2. Kebijakan Keamanan & Integritas Kode
*   **Keamanan Database:** Semua kueri database harus menggunakan *Query Binding* atau *Query Builder*. Dilarang keras menulis query mentah (*raw string*) tanpa binding guna mencegah *SQL Injection*.
*   **Integritas Transaksi:** Operasi multi-query wajib menggunakan mekanisme transaksi (`trans_start` dan `trans_complete` atau setara) untuk menjaga konsistensi data.
*   **Pencegahan Kehilangan Data (Data Loss Prevention):** Selalu lakukan verifikasi sebelum menjalankan perintah hapus data massal atau drop tabel database.

---

## 📝 3. Protokol Sinkronisasi Dokumentasi Otomatis (Doc-Sync Protocol)
Setiap kali AI Agent atau Developer melakukan perbaikan, modifikasi, atau penambahan fitur pada suatu modul di dalam folder `application/modules/[nama_modul]/`, Agen **WAJIB** secara langsung memperbarui file dokumentasi terkait di pustaka aturan terpusat:
1.  **Identifikasi Berkas Dokumentasi:**
    *   Everest: [modules](clients/everest/erp_web/modules/)`/[nama_modul].md`
    *   Indosan: [modules](clients/indosan/erp_web/modules/)`/[nama_modul].md`
2.  **Informasi yang Wajib Diperbarui:**
    *   Jika ada penambahan kode transaksi baru, daftarkan segera ke seksi `jenisTr` di berkas modul `.md` dan berkas kamus `kamus_transaksi.md` masing-masing klien.
    *   Jika ada penggunaan komponen bisnis baru (misal: `penulisan ganda stock locker` atau model baru), daftarkan ke seksi `components`.
    *   Perbarui deskripsi alur mutasi persediaan atau jurnal akuntansi jika logika bisnisnya berubah.
3.  **Pemberitahuan/Laporan:**
    *   Di akhir tugas, laporkan file `.md` mana saja yang telah diperbarui beserta ringkasan perubahannya.

---

## 💾 4. Protokol Caching Redis (Centralized Caching)
Setiap kali mengimplementasikan atau memodifikasi fitur caching menggunakan Redis (khususnya pada arsitektur PHP/CodeIgniter 3), ikuti standar berikut:

### 4.1 Konfigurasi Dasar & Isolasi Multi-Aplikasi (Prefix Otomatis)
*   Berkas konfigurasi koneksi diletakkan secara terpusat pada `application/config/redis.php`.
*   Parameter koneksi wajib mendefinisikan host, port, timeout (maksimum 1.5 detik agar tidak menghambat loading saat terjadi gangguan), dan password autentikasi jika diset di server.
*   **Isolasi Multi-Aplikasi (Zero-Config Prefixing):** Karena server Redis digunakan bersama oleh 50+ aplikasi, cache diisolasi secara otomatis menggunakan kombinasi `ENVIRONMENT` dan `NAMA_DATABASE` aktif dengan format:
    `[ENVIRONMENT]:[NAMA_DATABASE]:`
*   **Sistem Proteksi Domain (Lapis Pertahanan Kedua):** Driver `system/libraries/Cache/drivers/Cache_redis.php` telah dimodifikasi secara native agar:
    1. Membaca nama database aktif secara dinamis dari `$CI->db->database` atau file `config/database.php` (tanpa load koneksi DB prematur).
    2. Mendeteksi jika domain aplikasi (`HTTP_HOST`) diawali oleh `demo.mayagrahakencana.com`, maka status `ENVIRONMENT` akan **dipaksa (force)** menjadi `development`. Ini mencegah tabrakan data jika `index.php` tidak sengaja dikonfigurasi ke mode production pada server demo.

### 4.2 Keamanan & Penanganan Failover (Graceful Degradation)
*   **WAJIB** menyertakan backup adapter `dummy` saat memuat driver cache agar sistem tidak crash jika server Redis mati/unreachable:
    ```php
    $this->load->driver('cache', array('adapter' => 'redis', 'backup' => 'dummy'));
    ```
*   Setiap kueri Redis yang kritis harus memiliki penanganan error yang memadai (`try-catch` jika menggunakan PECL native secara langsung) untuk menghindari kegagalan sistem global.

### 4.3 Standar Penamaan Key (Key Naming Convention)
Gunakan prefix terstruktur untuk mencegah tabrakan data (*key collision*) antar-tabel atau modul:
*   **Status Penghapusan Data (`rel_deleters`):** `deleter_status_[MdlName]_[ID]`
*   **Status Kunci Stok (`baseModelLocker`):** `locker_status_[MdlName]_[ID]`
*   **Master Data Dropdown / Selector:** `lookup_all_[MdlName]`
*   **Data Spesifik User/Sesi:** Wajib menyertakan ID sesi atau ID user pada key untuk mencegah kebocoran data antar-pengguna: `[nama_data]_[USER_ID]`.

### 4.4 Kebijakan Invalidasi Cache (Cache Invalidation Policy)
*   Durasi kedaluwarsa (TTL) disesuaikan secara logis (misal: 24 jam untuk status relasi transaksi, 7 hari untuk master data dropdown).
*   Setiap kali terjadi operasi mutasi data (Create, Update, Delete, Batch Edit) pada model master yang di-cache, cache key terkait **WAJIB** langsung dihapus menggunakan `$this->cache->delete($key)` (atau helper pembersih cache sejenis) agar data yang disajikan ke pengguna tetap akurat.


### 5.0 semua yang berkaitan dengan kas, baik penerimaan maupun pengeluaran, format ui/ux pada tablenya, kolom harus membawa informasi seperti dibawah ini:

#penerimaan
* dibuat oleh: penagihan (nama invoicing)
* dibayar oleh: (nama konsumen) 
* diterima oleh: (nama kasir) 
 
#pembayaran hutang
* dibuat oleh: (nama pembelian)
* diserahkan oleh: (nama kasir)
* diterima oleh: (nama supplier/vendor)


# 📌 Panduan Aturan Indexing MySQL: Equality, Inequality, dan Klausa IN

Dokumen ini berisi aturan krusial dalam penulisan kueri MySQL agar tidak merusak atau mematikan fungsi index pada database.

---

## 1. Operator Equality (`=`)
Operator equality adalah operator yang paling ramah dan optimal terhadap index karena menggunakan pencarian presisi (*point lookup*).

### Aturan Utama:
* **Pemicu Index Maksimal**: MySQL akan langsung mendeteksi index dan memberikan status `ref` atau `const` pada analisis `EXPLAIN`.
* **Sempurna untuk Composite Index**: Jika Anda memiliki index gabungan (misal: kolom `A, B, C`), menggunakan equality pada kolom `A` dan `B` memungkinkan MySQL untuk terus membaca rantai index hingga kolom `C`.

---

## 2. Operator Inequality (`!=`, `<>`, `>`, `<`, `NOT IN`, `NOT LIKE`)
Operator inequality memaksa MySQL mencari data yang *bukan* atau *di luar* nilai tertentu. Operator ini berpotensi besar mematikan fungsi index.

### A. Efek `!=` dan `<>` (Tidak Sama Dengan)
* **Risiko**: Menggunakan `WHERE status != 'aktif'` membuat MySQL cenderung mengabaikan index dan melakukan **Full Table Scan** (`type: ALL`).
* **Alasan**: MySQL menilai membaca seluruh tabel sekaligus lebih murah dibanding melompat-lompat di dalam struktur pohon index (B-Tree) hanya untuk menghindari satu nilai.
* **Solusi**: Jika variasi datanya sedikit, ubah menjadi klausul `IN`.
  * *Buruk*: `WHERE status != 'aktif'`
  * *Baik*: `WHERE status IN ('pending', 'gagal')`

### B. Efek `>`, `<`, `>=`, `<=` (Pencarian Rentang / Range)
* **Risiko**: Operator rentang memicu pencarian bertipe `range`. Namun, operator ini **memutus rantai Composite Index**.
* **Contoh Kasus**:
  * *Struktur Index*: `(kategori, tanggal, status)`
  * *Kueri*: `WHERE kategori = 'buku' AND tanggal > '2026-01-01' AND status = 'lunas'`
  * *Dampak*: Index hanya bekerja sampai kolom `tanggal`. Kolom `status` diabaikan oleh index karena rantai index terputus oleh operator `>`.
* **Solusi**: Taruh kolom yang menggunakan operator range di posisi **paling akhir** saat membuat *composite index*.

### C. Efek `NOT IN` dan `NOT LIKE`
* **Risiko**: Memaksa database melakukan pemindaian menyeluruh (*Full Scan*).
* **Solusi**: Ubah kueri menggunakan pendekatan `LEFT JOIN ... WHERE tabel2.id IS NULL` yang jauh lebih ramah index.

---

## 3. Klausul `WHERE IN`
Klausul `IN` bertindak seperti gabungan beberapa kondisi `OR`. Index tetap aktif, namun dengan catatan tertentu.

### Aturan Utama:
* **Batas Jumlah Nilai**: Jika isi di dalam `IN (...)` terlalu banyak (misal ribuan ID), MySQL akan otomatis mematikan index dan memilih *Full Table Scan*.
* **Urutan Composite Index**: Berbeda dengan operator `>`, klausul `IN` **tidak memutus** rantai *composite index*. MySQL tetap bisa melanjutkan pencarian ke kolom index berikutnya.
* **Hindari Subquery Buruk**: Jangan gunakan `WHERE id IN (SELECT id FROM tabel_lain)`. Gunakan `INNER JOIN` agar index terbaca sempurna.

---

## 📊 Tabel Ringkasan & Solusi

| Operator | Efek terhadap Index | Solusi Terbaik Jika Lambat |
| :--- | :--- | :--- |
| **`=`** | ⭐ Sangat Baik (Optimal) | Pertahankan. Pastikan tipe data parameter dan kolom sama. |
| **`IN (...)`** | 👍 Baik (Batas Terbatas) | Jaga jumlah nilai di dalam `IN` agar tidak terlalu ribuan. |
| **`!=` atau `<>`** | ❌ Buruk (Memicu *Full Scan*) | Ubah jadi `IN (...)` jika variasi nilai penggantinya sedikit. |
| **`>` atau `<`** | ⚠️ Sedang (Memutus Composite) | Taruh kolom ini di posisi **paling akhir** dalam urutan *composite index*. |
| **`NOT IN`** | ❌ Buruk (Memicu *Full Scan*) | Ubah struktur kueri menggunakan `LEFT JOIN`. |

---

## 🛠️ Cara Memastikan Index Berjalan
Selalu uji kueri Anda menggunakan perintah `EXPLAIN` sebelum menaruhnya di sistem produksi:

```sql
EXPLAIN SELECT * FROM nama_tabel WHERE kategori = 'buku' AND status IN ('lunas', 'pending');
```

**Indikator Sukses:**
1. Kolom **`type`** berisi `ref`, `eq_ref`, atau `range` (bukan `ALL`).
2. Kolom **`key`** menampilkan nama index yang Anda buat (bukan `NULL`).

