# Runbook: Implementasi Enkripsi PII Pasien (UU PDP) — Production ## Ringkasan Enkripsi AES-256-GCM untuk data pribadi pasien dan data medis. Key disimpan di `.env`. Data asli di kolom `_enc`, kolom lama berisi masked value. Search pasien via trigram blind index (nama, HP, DOB, NIK). --- ## Urutan Eksekusi di Production ### 0. Pre-flight ```bash # Pastikan disk cukup (minimal 10GB free sebelum mulai) df -h / # Pastikan MySQL running mysql -e "SELECT 1;" # Catat ukuran tabel sebelum mysql -e "SELECT table_name, ROUND((data_length+index_length)/1024/1024,1) MB FROM information_schema.tables WHERE table_schema='one_lab' ORDER BY (data_length+index_length) DESC LIMIT 15;" ``` ### 1. Backup Database ```bash bash scripts/backup_pdp_tables.sh # Backup tersimpan di ~/backup_pdp_YYYY_MM_DD_HHMMSS/ ``` ### 2. Buat file `.env` ```bash cat > /path/to/one-api-lab/.env << 'EOF' IBL_ENCRYPT_KEY= IBL_ENCRYPT_SEARCH_KEY= EOF chmod 600 .env ``` > ⚠️ **WAJIB** simpan passphrase di password manager sebelum lanjut. > Key hilang = data tidak bisa didekripsi. ### 3. Jalankan SQL Migration (tambah kolom) ```bash mysql one_lab < sql/manual_changes/2026-05-31-pdp-encrypt-columns.sql mysql one_lab < sql/manual_changes/2026-05-31-pdp-update-triggers-enc.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';" ``` ### 4. Migration Data — Patient PII ```bash # Enkripsi m_patient dan m_patientaddress (178K + 133K rows) # Estimasi: 30-60 menit tergantung server php scripts/migrate_encrypt_patient.php # Verifikasi mysql -e "SELECT COUNT(*) total, COUNT(M_PatientName_enc) done FROM one_lab.m_patient;" mysql -e "SELECT COUNT(*) total, COUNT(M_PatientAddressDescription_enc) done FROM one_lab.m_patientaddress;" ``` ### 5. Migration Data — NIK Bidx ```bash # Populate search index untuk NIK (dari _enc yang sudah ada) php scripts/migrate_nik_bidx.php ``` ### 6. Migration Data — Address Enc ```bash # Enkripsi alamat (tanpa bidx — hemat disk) php scripts/migrate_address_enc.php ``` ### 7. Migration Data — Hasil Lab & Log ```bash # Enkripsi hasil lab (t_orderdetail, t_orderheader, so_resultentry*, dll) php scripts/migrate_encrypt_results.php # Enkripsi t_orderdelivery (email/HP tujuan pengiriman hasil) php scripts/migrate_encrypt_orderdelivery.php ``` ### 8. Masking Kolom Plaintext ```bash # Masking kolom lama agar controller lama tidak expose data lengkap php scripts/mask_patient_plaintext.php # Re-masking nama dengan format baru (kata pertama penuh + inisial) php scripts/remask_patient_name.php ``` ### 9. Verifikasi Akhir ```bash # Cek sample data sudah termasking mysql -e "SELECT M_PatientID, M_PatientName, M_PatientHP, M_PatientEmail FROM one_lab.m_patient LIMIT 5;" # Pastikan decrypt bisa berjalan php -r " define('BASEPATH', true); \$_ENV['IBL_ENCRYPT_KEY'] = trim(explode('=', file('.env')[0])[1]); \$_ENV['IBL_ENCRYPT_SEARCH_KEY'] = trim(explode('=', file('.env')[1])[1]); require 'application/libraries/Ibl_encryptor.php'; \$enc = new Ibl_encryptor(); \$row = (new PDO('mysql:host=localhost;dbname=one_lab', 'user', 'pass')) ->query('SELECT M_PatientName_enc FROM m_patient LIMIT 1')->fetch(); echo \$enc->decrypt(\$row['M_PatientName_enc']) . PHP_EOL; " # Cek disk usage setelah df -h / ``` --- ## Catatan Penting ### Key Management - Key disimpan di `.env` (JANGAN commit ke git — sudah di `.gitignore`) - Backup key di: password manager + file enkripsi di lokasi terpisah - Jika key hilang: data di `_enc` tidak bisa didekripsi ### Disk Space - Tambahkan minimal **8GB free** sebelum mulai di production - Kolom `_bidx` untuk nama/HP/DOB/NIK menambah ~500MB-1GB - Kolom `_enc` untuk semua field menambah ~200-300MB - `m_patientaddress` tidak punya `_bidx` (dihapus — hemat disk) ### Jika Disk Penuh ```bash # Cek pemakai disk terbesar du -sh /home/* /tmp/* /var/log/* 2>/dev/null | sort -rh | head -20 # Bersihkan journal (butuh sudo) sudo journalctl --vacuum-size=300M sudo truncate -s 0 /var/log/btmp ``` ### Field yang Dienkripsi #### `one_lab.m_patient` | Field | `_enc` | `_bidx` | |-------|--------|---------| | M_PatientName | ✅ | ✅ (search) | | M_PatientHP | ✅ | ✅ (search) | | M_PatientDOB | ✅ | ✅ (search) | | M_PatientNIK | ✅ | ✅ (search) | | M_PatientEmail | ✅ | — | | M_PatientPhone | ✅ | — | | M_PatientPOB | ✅ | — | | M_PatientIDNumber | ✅ | — | | M_PatientNIP | ✅ | — | #### `one_lab.m_patientaddress` | Field | `_enc` | `_bidx` | |-------|--------|---------| | M_PatientAddressDescription | ✅ | — (dihapus, hemat disk) | | M_PatientAddressEmail | ✅ | — | | M_PatientAddressPhone | ✅ | — | #### Hasil Lab - `t_orderdetail`: `T_OrderDetailResult`, `T_OrderDetailNote` - `t_orderheader`: `T_OrderHeaderDiagnose` - `t_orderdelivery`: `T_OrderDeliveryDestination` - `so_resultentrydetail`, `so_resultentry_fisik_umum`, dll - `mcu_resume_results`: `Mcu_ResumeResultsJSON` #### Log - `one_lab_log.log_patient`: `Log_PatientJsonBefore/After` - `one_lab_log.log_fo`: `Log_FoJson` ### Search Pasien Search parameter via `+` separator: ``` ?search=NAMA+HP+DOB+NIK ``` - `e[0]` = nama (trigram bidx, min 3 karakter) - `e[1]` = HP (trigram bidx, min 3 karakter) - `e[2]` = DOB format dd-mm-yyyy (trigram bidx) - `e[3]` = NIK (trigram bidx, min 3 karakter) ### Masking Format | Field | Contoh | |-------|--------| | Nama | `FAJRI H******* M****` | | HP | `0812*****890` | | Email | `fa***@gmail.com` | | NIK/IDNumber | `3201***01` | | POB | `JA***` | | Alamat | `Jl. S***` | ### Controller yang Sudah Diupdate (Read Full Data) - `mockup/fo/ibl_registration/Patient.php` — FO registration - `mockup/fo/ibl_registration/Order.php` — Order management - `mockup/fo/ibl_registration/Payment.php` - `mockup/fo/ibl_registration/History.php` - `mockup/fo/ibl_registration/Delivery.php` - `mockup/fo/ibl_registration/Order copy.php` - `mockup/masterdata/Patientv4.php` — Masterdata pasien (full data) ### Controller yang Belum Diupdate (Tampil Data Masked) Semua controller lain (~300+ file) otomatis menampilkan data termasking karena kolom plaintext sudah dimasking. Tidak perlu update satu-satu. ### Restore jika Ada Masalah ```bash mysql one_lab < ~/backup_pdp_YYYY_MM_DD_HHMMSS/one_lab_tables.sql mysql one_lab_log < ~/backup_pdp_YYYY_MM_DD_HHMMSS/one_lab_log_tables.sql ```