FHM09062601IBL - update runbook PDP: field tabel, DOB VARCHAR, NIK_bidx dari IDNumber, migration steps baru

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sas.fajri
2026-06-11 13:47:43 +07:00
parent 83bd46d521
commit f8d487079b
2 changed files with 33 additions and 49 deletions

View File

@@ -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

View File

@@ -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.