From f8d487079b85739df52dc2d815b79fcdb2bed81b Mon Sep 17 00:00:00 2001 From: "sas.fajri" Date: Thu, 11 Jun 2026 13:47:43 +0700 Subject: [PATCH] FHM09062601IBL - update runbook PDP: field tabel, DOB VARCHAR, NIK_bidx dari IDNumber, migration steps baru Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 36 ++++---------------------- docs/pdp-encryption-runbook.md | 46 +++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 49 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 08f64746..06109e36 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,38 +21,12 @@ ## PDP Encryption & BIRT Report -UU PDP No. 27/2022 mengharuskan enkripsi PII pasien. `M_PatientDOB`, `M_PatientName`, dll -di-mask di kolom plain, nilai asli ada di kolom `_enc` (AES-256-GCM). +Dokumentasi lengkap ada di **`docs/pdp-encryption-runbook.md`**. -### Pola kolom PDP di m_patient - -| Kolom plain | Tipe | Isi plain | `_enc` | `_bidx` | Sumber bidx | -|---|---|---|---|---|---| -| `M_PatientName` | VARCHAR | masked (`A*** B***`) | ✓ | ✓ | `M_PatientName` | -| `M_PatientHP` | VARCHAR | masked | ✓ | ✓ | `M_PatientHP` | -| `M_PatientDOB` | **VARCHAR(20)** | masked (`**-**-YYYY`) | ✓ | ✓ | `M_PatientDOB` (format d-m-Y) | -| `M_PatientIDNumber` | VARCHAR | masked (`1234**...**09`) | ✓ | — | — | -| `M_PatientNIK` | VARCHAR | plain (kosong/lama) | ✓ | ✓ | **`M_PatientIDNumber`** ← penting | - -`M_PatientDOB` diubah ke `VARCHAR(20)` (dari DATE) agar nilai masked `**-**-YYYY` bisa tersimpan. -`_mask_dob($v)` menerima format `d-m-Y` dan mengembalikan `**-**-YYYY`. - -**`M_PatientNIK_bidx` diisi dari `M_PatientIDNumber`**, bukan dari kolom `M_PatientNIK`. -Ini pola yang dipakai `ibl_registration/Patient.php` dan `Registrationv3.php`. -Search e[3] (format `Nama+HP+DOB+NIK`) menggunakan `JSON_CONTAINS(M_PatientNIK_bidx, '"hash"')`. - -Data lama yang disimpan sebelum pola ini diterapkan tidak akan punya `M_PatientNIK_bidx` -— perlu di-save ulang atau backfill script untuk bisa dicari by IDNumber. - -### Daftar migration PDP yang sudah diterapkan - -| File | Keterangan | -|---|---| -| `sql/manual_changes/2026-05-31-pdp-encrypt-columns.sql` | Tambah kolom `_enc` dan `_bidx` di m_patient, m_patientaddress, log tables | -| `sql/manual_changes/2026-05-31-pdp-update-triggers-enc.sql` | Update trigger untuk populate `_enc` | -| `sql/manual_changes/2026-06-08-pdp-fo-birt-sp-patient-print-cache.sql` | SP cache untuk BIRT | -| `sql/manual_changes/2026-06-11-alter-m-patient-dob-to-varchar.sql` | Ubah `M_PatientDOB` DATE → VARCHAR(20) | -| `sql/manual_changes/2026-06-11-alter-mcu-preregister-dob-to-varchar.sql` | Ubah `Mcu_PreregisterPatientsDOB` DATE → VARCHAR(20) | +Poin penting yang sering terlewat: +- `M_PatientNIK_bidx` diisi dari **`M_PatientIDNumber`**, bukan kolom `M_PatientNIK` +- `M_PatientDOB` bertipe `VARCHAR(20)` (bukan DATE) agar masked value `**-**-YYYY` tersimpan +- `Mcu_PreregisterPatientsDOB` juga `VARCHAR(20)` — tidak punya `_enc`, data asli di `m_patient` ### Pola wajib: PHP Proxy Stream diff --git a/docs/pdp-encryption-runbook.md b/docs/pdp-encryption-runbook.md index 5b11822c..9e4a3443 100644 --- a/docs/pdp-encryption-runbook.md +++ b/docs/pdp-encryption-runbook.md @@ -84,10 +84,17 @@ mysql one_lab < sql/manual_changes/2026-05-31-pdp-encrypt-columns.sql # Update trigger m_patient & m_patientaddress (pakai _enc di log JSON) mysql one_lab < sql/manual_changes/2026-05-31-pdp-update-triggers-enc.sql +# Ubah M_PatientDOB dari DATE ke VARCHAR(20) agar masked value tersimpan +mysql one_lab < sql/manual_changes/2026-06-11-alter-m-patient-dob-to-varchar.sql + +# Ubah Mcu_PreregisterPatientsDOB dari DATE ke VARCHAR(20) (sama) +mysql one_lab < sql/manual_changes/2026-06-11-alter-mcu-preregister-dob-to-varchar.sql + # Verifikasi kolom terbentuk mysql -e "SHOW COLUMNS FROM one_lab.m_patient LIKE '%_enc';" mysql -e "SHOW COLUMNS FROM one_lab.m_patient LIKE '%_bidx';" mysql -e "SHOW COLUMNS FROM one_lab.m_patientaddress LIKE '%_enc';" +mysql -e "SHOW COLUMNS FROM one_lab.m_patient WHERE Field = 'M_PatientDOB'\G" ``` --- @@ -258,17 +265,17 @@ mysql -e "SHOW STATUS LIKE 'Threads_connected';" ## Field yang Dienkripsi ### `one_lab.m_patient` -| Field | `_enc` | `_bidx` (search) | -|-------|:------:|:----------------:| -| M_PatientName | ✅ | ✅ | -| M_PatientHP | ✅ | ✅ | -| M_PatientDOB | ✅ | ✅ | -| M_PatientNIK | ✅ | ✅ | -| M_PatientEmail | ✅ | — | -| M_PatientPhone | ✅ | — | -| M_PatientPOB | ✅ | — | -| M_PatientIDNumber | ✅ | — | -| M_PatientNIP | ✅ | — | +| Field | Tipe kolom plain | `_enc` | `_bidx` (search) | Catatan | +|-------|:---:|:------:|:----------------:|---------| +| M_PatientName | VARCHAR | ✅ | ✅ | | +| M_PatientHP | VARCHAR | ✅ | ✅ | | +| M_PatientDOB | **VARCHAR(20)** | ✅ | ✅ | Diubah dari DATE → VARCHAR agar mask `**-**-YYYY` tersimpan | +| M_PatientNIK | VARCHAR | ✅ | ✅ | ⚠️ `M_PatientNIK_bidx` diisi dari **`M_PatientIDNumber`**, bukan NIK | +| M_PatientEmail | VARCHAR | ✅ | — | | +| M_PatientPhone | VARCHAR | ✅ | — | | +| M_PatientPOB | VARCHAR | ✅ | — | | +| M_PatientIDNumber | VARCHAR | ✅ | — | Masked plain, bidx-nya lewat `M_PatientNIK_bidx` | +| M_PatientNIP | VARCHAR | ✅ | — | | ### `one_lab.m_patientaddress` | Field | `_enc` | `_bidx` | @@ -373,13 +380,16 @@ mysql one_lab < sql/manual_changes/2026-05-31-pdp-birt-sp-cache-join.sql Data PII yang dimasking saat INSERT ke staging table `mcu_preregister_patients`: -| Field | Mask | -|-------|------| -| `*PatientName` | `_mask_name()` | -| `*KTP` | `_mask_id()` | -| `*NIP` / `*NIK` | `_mask_id()` | -| `*Email` | `_mask_email()` | -| `*Hp` | `_mask_phone()` | +| Field | Tipe kolom | Mask | +|-------|:---:|------| +| `*PatientName` | VARCHAR | `_mask_name()` | +| `*KTP` | VARCHAR | `_mask_id()` | +| `*NIP` / `*NIK` | VARCHAR | `_mask_id()` | +| `*Email` | VARCHAR | `_mask_email()` | +| `*Hp` | VARCHAR | `_mask_phone()` | +| `*DOB` | **VARCHAR(20)** | `_mask_dob()` — diubah dari DATE → VARCHAR agar mask `**-**-YYYY` tersimpan | + +Tidak ada kolom `_enc` di tabel ini — data asli bisa diambil dari `m_patient` via `*M_PatientID`. 4 lokasi INSERT yang sudah diupdate: `savecsv()` & `save()` di setupmcuoffline-ibl, `save()` & `savenewform()` di mcuoffline/Preregisterapp.