Files
satusehat-worker/docs/PRD.md
T
2026-08-05 06:47:59 +00:00

10 KiB
Raw Blame History

📑 Product Requirements Document (PRD)

Nama Produk: GoPrint Service General — SatuSehat Bridging & SIMRS Master Gateway Repository: worker-satusehat Versi Dokumen: 1.0 Tanggal: 2026-05-13 Status: DRAFT (sinkron dengan kondisi kode terkini)


1. Latar Belakang

Fasilitas kesehatan (faskes) di Indonesia wajib melaporkan transaksi pelayanan medis ke platform nasional SatuSehat (Kemenkes RI) dalam format FHIR R4, dan tetap terhubung dengan layanan BPJS Kesehatan (VClaim / Antrol / Apotek / IHS) untuk klaim & antrean. Saat ini Sistem Informasi Manajemen Rumah Sakit (SIMRS) lokal tidak dirancang untuk menangani latensi, autentikasi (OAuth2 + HMAC + AES), dan rate limit dari API pemerintah secara langsung.

Visi: GoPrint Service General menjadi bridging gateway tunggal yang:

  1. Memisahkan beban integrasi eksternal dari SIMRS inti.
  2. Menjamin pengiriman data ke SatuSehat tahan terhadap rate limit dan kegagalan token.
  3. Menyediakan abstraksi REST/gRPC sederhana bagi tim aplikasi internal.
  4. Menampung modul administrasi (RBAC hierarkis, master data) yang dipakai bersama oleh seluruh aplikasi rumah sakit.

2. Pengguna & Persona

Persona Interaksi Kebutuhan Utama
SIMRS Backend / Aplikasi Klinis Konsumsi REST /api/v1/... & gRPC :9090 Latensi rendah, abstraksi FHIR, tidak menangani token SatuSehat sendiri
Worker (Sub-system internal) Polling DB SIMRS → POST ke API internal service-satusehat Pengiriman asinkron, recovery 401/429, tracker per resource
Admin Faskes (IT) Web UI (eksternal) memanggil REST RBAC CRUD role/pages/permission hirarkis, cache invalidasi otomatis
DevOps / Operator Dashboard log + metrik Log JSON terstruktur (WIB), Prometheus, graceful shutdown
Auditor Kemenkes Tidak langsung — via histori sync Jejak audit per dokumen (request, response, FHIR ID)

3. Ruang Lingkup Fitur (Scope)

3.1. Modul Integrasi Eksternal

A. SatuSehat (Kemenkes)

  • Klien resmi satusehat.SatuSehatClient (client.go):
    • OAuth2 client-credentials dengan caching token + safety margin 60 detik.
    • Auto-retry pada HTTP 401 (refresh token, request ulang).
    • Tiga endpoint terpisah: DoRequest (FHIR R4), DoKFA (master farmasi), DoConsent.
  • FHIRPayload Builder (types.go): fluent interface (Set/Append/ToJSON) untuk membangun payload resource FHIR tanpa risiko nil pointer.
  • Resource yang DIDUKUNG (struktur worker tersedia di internal/worker/satusehat/):
    • Implementasi lengkap (ready-to-activate): Encounter, ImagingStudy, ServiceRequest (default + radiology), Medication, MedicationRequest, MedicationDispense.
    • Kerangka stub (perlu pengisian logika sinkron): AllergyIntolerance, CarePlan, ClinicalImpression, Composition, Condition, DiagnosticReport, EpisodeOfCare, Immunization, MedicationStatement, Observation, Procedure, QuestionnaireResponse, Specimen.

B. BPJS Kesehatan

  • Klien resmi bpjs.Client (client.go):
    • Header otomatis X-cons-id, X-timestamp, X-signature (HMAC-SHA256).
    • Dekripsi respons V2 (AES-256-CBC, key = SHA256(ConsID+SecretKey+Timestamp), IV = 16 byte awal key, padding PKCS7).
    • Auto-decompression berurutan: LZString → Gzip → plaintext JSON.
  • Service yang siap: VClaim, AntreanRS, AntreanFKTP, Aplicare, Apotek, PCare, ICare, ERekamMedis. Belum terhubung sebagai worker aktif — disediakan sebagai SDK on-demand.

C. Master KFA (Kamus Farmasi & Alkes)

  • Worker KFA Master Puller (puller.go):
    • Polling halaman /satusehat/reference/kfa/products?product_type=farmasi via API internal service-satusehat.
    • Fetch detail per kfa_code, UPSERT bundle 3 tabel: kfa_product, kfa_product_active_ingredient, kfa_product_packaging.
    • Pencegahan rate-limit: 500ms antar item, 30s pada 429 list API, 60s pada 429 detail API, reset ke halaman 1 + idle 6 jam jika halaman kosong.
    • Status: SATU-SATUNYA WORKER YANG AKTIF di runtime saat ini.

3.2. Modul Internal (System Management)

A. Multi-Database & CQRS

  • Database Manager mendukung PostgreSQL, MySQL, SQL Server, SQLite, MongoDB melalui GORM + sqlx + driver native.
  • Setiap modul bisnis (auth, role/pages, role/permission, role/master, kfa) mengikuti pola:
    • CommandRepository (GORM, write → primary DB)
    • QueryRepository (sqlx raw SQL, read → replica jika dikonfigurasi)
    • Service (orkestrasi, validasi, cache-aside)
  • Multi-koneksi sekaligus (config: databases.postgres, databases.satudata, databases.simrs).

B. RBAC Hierarkis

  • Empat sub-modul (internal/master/role/):
    • master — definisi role induk.
    • pages — daftar halaman/menu dengan parent-child + level.
    • permission — CRUD permission per role per page (Create/Read/Update/Delete/Disable).
    • accses — endpoint agregasi GetRoleAccess(userID) untuk konsumsi UI.
  • Caching tree menu via Redis dengan kunci hash SHA-256 dari parameter query; invalidate by prefix pada mutasi.

C. Transport

  • REST API (Gin) — port 8080 default, registry-based service wiring di http/servers, Swagger UI (/docs/swagger).
  • gRPC (port 9090 default) — kerangka tersedia, registrasi handler belum diaktifkan (main.go:200-204permissionHandler masih dikomentari).
  • Middleware: Auth (JWT/Keycloak/Static/Hybrid), CORS, Request-ID, rate-limit Redis-backed.

D. Auth Pluggable

  • Provider yang didukung di config: jwt (default), keycloak, static, hybrid dengan fallback. JWT signing key, Keycloak issuer/JWKS URL semuanya via env.

3.3. Object Storage

  • MinIO/S3 terkoneksi via interfaces/minio untuk penyimpanan dokumen klinis (PDF, hasil radiologi) — diinisialisasi di startup.

3.4. Observability

  • Logger Logrus kustom (JSON, WIB timezone, rotasi harian logs/YYYY/MM/YYYY-MM-DD.log).
  • Prometheus client (prometheus/client_golang) ter-import; metric endpoint perlu dipasang di routes.
  • Field log standar: service, environment, request_id, caller, function_name.

4. Persyaratan Non-Fungsional

Kategori Target
Latensi REST internal p95 ≤ 200 ms (cache hit), ≤ 800 ms (cache miss + DB query)
Throughput Worker KFA ≥ 100 produk / menit (dibatasi rate limit Kemenkes)
Ketahanan API gov't Retry otomatis pada 401 (refresh), 429 (sleep 30-60s), 5xx (retry dengan backoff)
Availability 99.5% (single-instance), 99.9% (multi-instance — butuh migrasi tracker DB)
Resource startup Token initial login, retry 6×, fail-fast Fatal jika tidak berhasil
Graceful shutdown SIGTERM → errgroup cancel → wait-group worker → close DB & cache
Keamanan TLS pada API gov't, parameter binding SQL, payload BPJS dekripsi sebelum log, password DB & secret via env
Konfigurasi Viper YAML + overlay env var (DATABASES_POSTGRES_HOST dsb)

5. Asumsi & Ketergantungan

  • API internal service-satusehat (port 8096 default, internal_fhir_server_url) sudah running dan menyediakan endpoint:
    • /auth/login, /auth/refresh — token JWT untuk worker.
    • /satusehat/reference/kfa/products & /products/{kfa_code}.
    • /satusehat/medication, /satusehat/imaging-study, /satusehat/service-request, dst. — proxy ke Kemenkes.
  • Database SIMRS read-only (atau read-write via koneksi simrs/satudata) berisi tabel sumber: m_pasien, transaksi pesan obat, dispensing, imaging study order.
  • Redis tersedia untuk cache + rate-limit; tanpa Redis sistem fallback ke NoOp cache (bukan failure).
  • Akses outbound ke https://api-satusehat.kemkes.go.id dan https://apijkn.bpjs-kesehatan.go.id.

6. Kriteria Sukses (Acceptance Criteria)

v1 (Saat Ini — Production untuk KFA saja)

  • Service start dengan REST + gRPC + KFA Worker tanpa error.
  • Master KFA tertarik secara periodik & ter-UPSERT lengkap ke 3 tabel.
  • RBAC CRUD via REST berfungsi, cache hit > 80% setelah warm-up.
  • Login worker SatuSehat berhasil retry 6× sebelum fatal.

v1.x (Aktivasi Worker Klinis — Target Q3 2026)

  • Worker Medication, MedicationRequest, MedicationDispense aktif → sync log tersimpan, mapping file harian terbentuk, FHIR ID kembali dan tersimpan.
  • Worker ServiceRequest (Radiology) & ImagingStudy aktif end-to-end.
  • Worker Encounter aktif sebagai prasyarat referensi resource lain.
  • Bug satusehatClient = nil di main.go:235 diselesaikan.

v2 (Stateless & Event-Driven — Target Q4 2026 / Q1 2027)

  • State tracker (*.txt) dipindah ke tabel sync_tracker atau Redis hash → mendukung multi-replica.
  • Kafka producer aktif (saat ini dikomentari di main.go:111-113).
  • PostgreSQL LISTEN/NOTIFY menggantikan sebagian polling worker.
  • Endpoint manual retry per sync_log.id untuk koreksi data.

7. Di Luar Cakupan (Out of Scope)

  • UI dashboard (akan dibangun di repository terpisah, frontend).
  • Sinkron pasien (internal/worker/patient/migrator.go) — kode tersedia tapi tidak dipanggil dari main.go / worker.go; dianggap deprecated atau tugas migrasi one-shot manual.
  • 13 resource FHIR yang masih stub (lihat §3.1.A) — diaktifkan setelah 6 resource utama stabil.
  • Integrasi BPJS aktif sebagai worker — disediakan sebagai SDK, use case belum dikonfirmasi.

8. Risiko & Mitigasi

Risiko Dampak Mitigasi
Tracker .txt korup / race antara replica Duplikasi atau data lost saat pengiriman Pindah ke DB row-locked atau Redis INCR (Devplan Phase 2).
Token SatuSehat expired di tengah burst Worker stuck 401 Sudah ditangani: refresh dengan mutex + fallback re-login (auth.go).
Rate limit Kemenkes berubah Throughput turun Setiap worker punya konstanta rateLimitSleep per resource — bisa di-tune via config (rekomendasi).
Password hardcoded di patient/migrator.go:23-26 Keamanan jika diaktifkan Hapus default atau wajibkan env var sebelum digunakan.
Bug nil SatuSehat client di main Panic jika worker yang membutuhkan diaktifkan Inisialisasi via satusehat.NewClient(cfg) sebelum worker.NewManager.

Disusun ulang: Tim Engineering GoPrint, 2026-05-13.