Mengatur Hak Akses Casemix di RME Biar Tidak Bisa Ubah Diagnosis Dokter

“Mas, data diagnosis pasien tiba-tiba berubah. Padahal dokter bilang belum pernah edit.” Pernah kena kasus kayak gini, Sobat IT RS? Data diagnosis yang tiba-tiba berubah, kadang bikin audit internal jadi mumet. Apalagi kalau temuan ini datang pas audit eksternal, bisa bikin kepala pusing tujuh keliling. Salah satu biangnya: privilege akses Casemix di RME yang terlalu longgar. Banyak user yang semestinya hanya bisa view, malah bisa edit diagnosis dokter. Ujung-ujungnya, integritas rekam medis bisa kacau, jejak audit juga jadi abu-abu.

Artikel ini bahas gimana ngatur hak akses Casemix di RME (Rekam Medis Elektronik) supaya diagnosis dokter tidak bisa diubah sembarangan. Fokus di level database, bukan cuma permukaan aplikasi. Langsung ke praktek: contoh struktur tabel, query privilege, sampai best practice audit trail.

Kenapa Diagnosis Gampang Diubah?

Penyebab utama: role dan privilege di database dibuat asal-asalan. Kadang karena buru-buru, kadang karena “biar gampang input” pas proses klaim BPJS. Model begini sering kejadian:

  • Satu user Casemix bisa akses seluruh data pasien, termasuk UPDATE diagnosis dokter.
  • Hak akses write diberikan ke semua user yang seharusnya hanya read-only.
  • Audit trail lemah atau bahkan ga ada tracking perubahan.

Efeknya? Diagnosis bisa diedit seenaknya, bukan oleh dokter yang bertanggung jawab. Data rekam medis jadi rawan manipulasi, compliance audit jadi gagal.

Studi Kasus: Struktur Tabel Diagnosis & Casemix

Contoh nyata di lapangan, umumnya ada dua jenis tabel:

  • diagnosis: berisi data diagnosis asli yang di-input dokter.
  • casemix_claim: berisi data klaim BPJS, kadang copy-an dari diagnosis dokter tapi boleh diedit oleh tim Casemix buat penyesuaian coding klaim.

Struktur sederhana seperti ini:

-- Tabel diagnosis
CREATE TABLE diagnosis (
  id SERIAL PRIMARY KEY,
  pasien_id INT NOT NULL,
  dokter_id INT NOT NULL,
  kode_icd10 VARCHAR(10) NOT NULL,
  deskripsi TEXT,
  tgl_input TIMESTAMP NOT NULL DEFAULT NOW(),
  created_by INT NOT NULL,
  updated_by INT,
  updated_at TIMESTAMP
);

-- Tabel casemix_claim
CREATE TABLE casemix_claim (
  id SERIAL PRIMARY KEY,
  pasien_id INT NOT NULL,
  kode_icd10 VARCHAR(10) NOT NULL,
  deskripsi TEXT,
  sumber_diagnosis_id INT, -- FK ke diagnosis.id
  tgl_klaim TIMESTAMP NOT NULL DEFAULT NOW(),
  created_by INT NOT NULL,
  updated_by INT,
  updated_at TIMESTAMP
);

Problem sering muncul karena privilege user Casemix terlalu lebar pada tabel diagnosis. Padahal mereka cukup read-only ke diagnosis, dan write cukup ke casemix_claim.

Mapping Role & Privilege: Jangan Kasih Semua Hak

Role Umum di RME & Casemix

  • Dokter: input, edit diagnosis pada pasien sendiri.
  • Casemix: lihat diagnosis dari dokter (untuk kebutuhan klaim), tidak bisa edit diagnosis asli, hanya bisa write di tabel klaim.
  • Admin RME: akses penuh, termasuk perubahan data untuk keperluan audit/maintenance.

Privilege Minimal di Database

  • Dokter: SELECT, INSERT, UPDATE di diagnosis (hanya pada diagnosis sendiri).
  • Casemix: SELECT di diagnosis; SELECT, INSERT, UPDATE di casemix_claim.
  • Admin RME: ALL PRIVILEGES di kedua tabel (control terbatas, jangan kasih ke semua orang).

Implementasi di PostgreSQL

-- Buat role
CREATE ROLE dokter;
CREATE ROLE casemix;
CREATE ROLE admin_rme;

-- Assign privilege untuk diagnosis
GRANT SELECT, INSERT, UPDATE ON diagnosis TO dokter;
GRANT SELECT ON diagnosis TO casemix;
GRANT ALL PRIVILEGES ON diagnosis TO admin_rme;

-- Assign privilege untuk casemix_claim
GRANT SELECT, INSERT, UPDATE ON casemix_claim TO casemix;
GRANT ALL PRIVILEGES ON casemix_claim TO admin_rme;

Jangan lupa revoke default privilege dari PUBLIC:

REVOKE ALL ON diagnosis FROM PUBLIC;
REVOKE ALL ON casemix_claim FROM PUBLIC;

Proteksi Tambahan: Row-Level Security (RLS)

Privilege di atas sebenernya sudah lumayan. Tapi kadang role “dokter” kepentok: mereka bisa update diagnosis dokter lain. Di sini, fitur Row-Level Security (RLS) PostgreSQL bisa bantu batasi sampai level baris (row) data.

Aktifkan RLS

ALTER TABLE diagnosis ENABLE ROW LEVEL SECURITY;

-- Policy supaya dokter hanya bisa akses diagnosis milik sendiri
CREATE POLICY dokter_akses_sendiri
  ON diagnosis
  FOR ALL
  TO dokter
  USING (dokter_id = current_setting('myapp.current_user_id')::int);

Pakai SET session variable myapp.current_user_id tiap login dokter:

SET myapp.current_user_id = 123; -- id dokter login

Dengan RLS, dokter cuma bisa read/write diagnosis pasien yg mereka create. Casemix tetap cuma bisa read, admin tetap superuser.

RLS di Casemix, Perlu?

Biasanya engga, karena Casemix memang cuma read diagnosis. Tapi kalau ada kebutuhan “Casemix tertentu hanya boleh akses pasien di wilayah X”, bisa tambah policy serupa.

Audit Trail: Pantau Perubahan Diagnosis

Privilege sudah rapet, kadang tetap perlu bukti siapa terakhir ubah diagnosis. Minimal wajib ada log perubahan diagnosis (insert/update/delete). Pilihan:

  • Field updated_by, updated_at di tabel diagnosis. Setiap UPDATE, field ini diisi.
  • Log table terpisah (best practice): semua perubahan diagnosis di-log ke tabel baru.

Trigger Untuk Audit Trail Diagnosis

Contoh trigger untuk log perubahan diagnosis:

-- Tabel log perubahan diagnosis
CREATE TABLE diagnosis_audit (
  id SERIAL PRIMARY KEY,
  diagnosis_id INT NOT NULL,
  action VARCHAR(10) NOT NULL, -- INSERT/UPDATE/DELETE
  data_lama JSONB,
  data_baru JSONB,
  changed_by INT,
  changed_at TIMESTAMP NOT NULL DEFAULT NOW()
);

-- Trigger function
CREATE OR REPLACE FUNCTION log_diagnosis_update()
RETURNS TRIGGER AS $$
BEGIN
  IF TG_OP = 'UPDATE' THEN
    INSERT INTO diagnosis_audit (diagnosis_id, action, data_lama, data_baru, changed_by)
    VALUES (
      NEW.id, 'UPDATE', row_to_json(OLD), row_to_json(NEW), NEW.updated_by
    );
  ELSIF TG_OP = 'DELETE' THEN
    INSERT INTO diagnosis_audit (diagnosis_id, action, data_lama, changed_by)
    VALUES (
      OLD.id, 'DELETE', row_to_json(OLD), OLD.updated_by
    );
  ELSIF TG_OP = 'INSERT' THEN
    INSERT INTO diagnosis_audit (diagnosis_id, action, data_baru, changed_by)
    VALUES (
      NEW.id, 'INSERT', row_to_json(NEW), NEW.created_by
    );
  END IF;
  RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- Assign trigger ke tabel diagnosis
CREATE TRIGGER diagnosis_audit_trigger
AFTER INSERT OR UPDATE OR DELETE ON diagnosis
FOR EACH ROW EXECUTE FUNCTION log_diagnosis_update();

Sekarang, tiap diagnosis diubah, log langsung masuk diagnosis_audit. Field changed_by isi user pengubah. Audit trail aman, bisa dilacak siapa ubah apa, kapan.

Jangan Lupa: Hardening Koneksi Aplikasi & User Mapping

  • Pastikan aplikasi connect ke DB pakai user/role yang privilege-nya sudah dibatasi di atas (bukan pakai superuser, bukan “sa”).
  • Map user aplikasi ke role DB secara jelas. Contoh, login Casemix, aplikasi connect ke DB pakai user “app_casemix” yang role-nya hanya casemix.
  • Hati-hati feature override di aplikasi yang bisa “impersonate” user. Bisa bobol proteksi DB kalau asal-asalan.

Anti-Modif Diagnosis: Contoh SQL Query Monitoring

Curiga diagnosis diubah Casemix? Cek log audit:

SELECT * FROM diagnosis_audit
WHERE action = 'UPDATE'
  AND data_lama -> 'updated_by' >> 'role' = 'casemix'
ORDER BY changed_at DESC;

Atau, cek langsung tabel diagnosis, siapa yang terakhir mengubah:

SELECT d.id, d.kode_icd10, d.updated_by, u.nama_user
FROM diagnosis d
JOIN users u ON d.updated_by = u.id
WHERE d.updated_by IN (SELECT id FROM users WHERE role = 'casemix');

Ketahuan Casemix pernah update diagnosis? Pertanda privilege bocor, atau aplikasi belum beres masking role.

Best Practice: Integrasi Proteksi di DB dan Aplikasi

  • Jangan cuma proteksi di aplikasi (frontend/backend), karena user bisa tembus lewat script/koneksi langsung.
  • DB layer wajib dikunci privilege-nya, role mapping jelas. Aplikasi cukup tambah validasi di level bisnis.
  • Pastikan semua perubahan diagnosis selalu audit log. Periodik review log audit, cari perubahan aneh.
  • Training user Casemix untuk tidak minta “akses penuh diagnosis” demi kemudahan input klaim.
  • Migrasi dari “copy-paste diagnosis ke tabel klaim” ke mekanisme reference (pakai sumber_diagnosis_id), supaya data tidak dobel dan gampang audit.

Checklist: Ngunci Hak Akses Casemix

  • Bedakan role dokter, casemix, admin di user aplikasi & DB
  • Set privilege minimal di DB (GRANT/REVOKE)
  • Aktifkan Row-Level Security di diagnosis
  • Implementasi audit trail perubahan diagnosis
  • Map user aplikasi ke role DB yang sesuai
  • Review log audit diagnosis rutin

Studi Lapangan: Problem Real di RS

“Pak, diagnosis saya berubah sendiri. Kok bukan saya yang input?”—Kejadian ini real di rumah sakit swasta, gara-gara user Casemix dikasih akses update ke tabel diagnosis. Awalnya biar cepet input klaim, lama-lama diagnosis diubah tanpa sepengetahuan dokter. Akhirnya, ketika audit BPJS datang, semua jadi ribet. Setelah hak akses dikunci, masalah selesai. Tim Casemix tetap bisa proses klaim tanpa utak-atik diagnosis asli.

Penutup: Integritas Data = Harga Mati

Diagnosis dokter = data sensitif. Integritas dan jejak audit harus dijaga. Ngatur privilege Casemix di RME bukan cuma soal compliance, tapi juga keamanan dan kepercayaan sistem. Jangan kasih privilege lebih dari yang diperlukan. Audit trail wajib. Kalau belum beres, fix sekarang sebelum kebobolan.