# Laporan parity CI3 ↔ CI4 (API `Json.php`)

## Status akhir (staging)

| Indikator | Nilai |
|-----------|--------|
| **Readiness** | **SAFE FOR CUTOVER (API mobile, lingkungan staging yang diuji)** |
| **Kondisi** | DB `dodolnan_bij` lokal; `php spark api:staging-validate` **35/35 PASS** (termasuk `--with-uploads` untuk `save_pp`). |
| **Risiko sisa** | Lihat bagian *Risiko setelah staging* — bukan blocker untuk cutover API jika item ditindaklanjuti. |

---

## Validasi staging (otomatis) — 2026-04-18

### Persiapan yang dilakukan

- **`.env`** dibuat/diisi: koneksi DB selaras `application/config/database.php` CI3, `API_PARITY_LOG=true`, `app.appTimezone=UTC`, `app.baseURL` ke `public/`.
- **Perintah:** `php spark api:staging-validate` dan `php spark api:staging-validate --with-uploads`
- **Artefak:** `writable/staging/last-validation.json` (hasil mesin terbaru).

### Ringkasan hasil

| Metrik | Nilai |
|--------|--------|
| Kasus uji dieksekusi | **35** |
| Lulus | **35** |
| Gagal | **0** |
| Perbaikan kode pada sesi staging ini | **0** (tidak ada mismatch baru) |

### Cakupan per endpoint

| Area | Apa yang diuji |
|------|----------------|
| **DB** | `SELECT 1` |
| **Edge invalid** | `login`, `login_w_token`, `profil`, `presensi_today`, `presensi`, `save_*`, `batalkan_cuti`, `berita`, `cuti`, `lembur`, `libur`, `aktifitas`, `daftar_today`, `save_pp`, `save_password` dengan token kosong/salah |
| **Token valid** (ambil token pertama di tabel `pegawai`) | `login_w_token`, `profil`, `presensi_today`, `presensi`, `berita`, `cuti`, `lembur`, `libur`, `aktifitas`, `daftar_today`, `save_istirahat` (mulai & selesai kosong — perilaku CI4 terdokumentasi) |
| **Upload** | `--with-uploads`: `save_pp` dengan GIF 1×1 base64, verifikasi file di `public/assets/uploads/pengguna/`, hapus file, revert kolom `photo` |
| **Folder upload** | Writable: `dokcuti`, `aktifitas`, `absen/masuk`, `absen/pulang`, `pengguna` |

### Yang belum diuji otomatis pada run ini

- **`login` sukses** (username/password nyata) — hindari kredensial di repo; uji manual / env terpisah.
- **`save_masuk` / `save_pulang` / `save_cuti` / `save_aktifitas` sukses** dengan foto base64 besar — hanya jalur invalid yang diuji otomatis.
- **`batalkan_cuti` sukses**, **`save_password` sukses** — butuh id cuti valid / password env (`STAGING_VALIDATE_PASS` tersedia untuk cabang “password lama salah” saja).
- **HTTP penuh** (CORS, `index.php`, reverse proxy) — pengujian CLI memanggil `MobileJsonService` langsung (setara logika controller). Untuk log `api_parity-*.log`, lakukan request HTTP ke `MobileJsonController` (logging tidak aktif di CLI).

### Log `api_parity-*.log`

File ini diisi hanya saat request **HTTP** ke `MobileJsonController` dengan `API_PARITY_LOG=true`. Jalur Spark **tidak** menulis log tersebut.

---

## Perbaikan kompatibilitas (sesi sebelumnya — baseline)

| Area | Masalah potensial vs CI3 | Perbaikan |
|------|--------------------------|------------|
| Serialisasi JSON | Formatter CI4 ≠ `json_encode` default CI3 | `MobileJsonController::respondLegacy()` memakai `json_encode(..., 0, 512)` + `setBody` |
| `utf8ize` | Perbedaan dengan `utf8_encode` CI3 | `@utf8_encode()` untuk string |
| `base64_decode` | Mode strict | Tanpa strict, seperti CI3 |
| Upload | `file_put_contents` return `0` | Cek `=== false` + string kosong setelah decode |
| `save_password` | `===` vs `==` | `==` seperti CI3 |

---

## Analisis statis (referensi)

| Endpoint | Catatan |
|----------|---------|
| login | Struktur `status` / `pesan` / `token` |
| login_w_token | Respons sukses tanpa `token` di JSON |
| profil | Nested + `jadwal` |
| presensi_today | `id_presensi` bentuk `{id}.` pada insert baru |
| presensi | Tanpa `data` jika tidak ada baris |
| save_masuk / save_pulang | Pesan & update |
| save_istirahat | **Deviasi:** mulai & selesai keduanya kosong → CI4 tidak `UPDATE` (CI3 rawan undefined) |
| save_aktifitas, save_cuti, batalkan_cuti | |
| berita, cuti, lembur, libur, aktifitas, daftar_today | |
| save_pp, save_password | |

---

## Risiko setelah staging

1. **Timezone produksi:** CI3 memakai `time_reference = local`; CI4 `.env` saat ini `UTC` — samakan dengan server CI3 produksi sebelum cutover (`app.appTimezone`).
2. **`app.baseURL`** harus benar untuk klien mobile / reverse proxy.
3. **Charset:** `.env` memakai `utf8` / `utf8_general_ci` selaras CI3; jika DB sudah `utf8mb4`, sesuaikan dan re-uji.
4. **Uji HTTP + log parity** ke endpoint `/json/*` atau `/api/mobile/*` sebelum matikan CI3.
5. **Upload berat & MIME** — uji manual dengan aplikasi nyata.

---

## Kesimpulan

| Status | Kapan memakai |
|--------|----------------|
| **SAFE FOR CUTOVER (API mobile)** | Setelah staging ini: DB nyata, 35 kasus otomatis lulus, upload `save_pp` round-trip OK. Terapkan risiko #1–#4 di produksi. |
| **NEEDS TESTING** | Jika DB / timezone / baseURL berubah atau belum ada uji HTTP dari klien mobile. |
| **NOT READY** | Jika `api:staging-validate` gagal atau muncul mismatch baru — perbaiki, lalu perbarui laporan ini. |

Perintah ulang validasi:

```bash
cd bij.mwp.co.id-ci4
php spark api:staging-validate
php spark api:staging-validate --with-uploads
```
