Files
satusehat-worker/docs/QMD.md
T
2026-07-29 06:38:42 +00:00

8.9 KiB
Raw Blame History

🛡️ Quality Management Document (QMD)

Project: GoPrint Service General (worker-satusehat) Versi: 1.0 Tanggal: 2026-05-13

Dokumen ini merangkum standar mutu, pola tata-kelola kode, dan kontrol resiko yang berlaku pada codebase. Setiap item disertai titik verifikasi (file/fungsi) supaya bisa diaudit ulang.


1. Standar Arsitektur

1.1 Clean Architecture + CQRS

Setiap modul bisnis (auth, master/role/*, master/kfa, worker/satusehat/*) WAJIB terdiri minimal dari:

  • entity.go — definisi domain (GORM struct).
  • dto.go — request/response & filter.
  • repository.go — terpisah CommandRepository (GORM, primary) dan QueryRepository (sqlx, read replica).
  • service.go — orkestrasi, validasi, integrasi cache.
  • mapper.go — DTO ↔ Entity (anti-leak GORM tag).

Generator boilerplate tersedia: lihat scripts/ dan tools/generate.go. Wajib digunakan untuk modul baru supaya struktur konsisten.

1.2 Pembagian Tanggung Jawab Worker

Setiap worker SatuSehat di internal/worker/satusehat/<resource>/ menggunakan kontrak yang seragam:

  • Config{ DBManager, InternalBaseURL, OrganizationID }
  • TokenManager interface (GetAccessToken, ForceRefreshAndGetToken) — di-implement oleh worker.Manager.
  • Run(ctx context.Context) — long-running loop dengan select-context untuk graceful shutdown.
  • Tracker per modul (last_*_id.txt / last_*_time.txt) — to be migrated to DB.

2. Observability & Logging

2.1 Logger (pkg/logger)

  • Wrapper Logrus dengan format JSON otomatis di mode production, text-formatted di development.
  • localTimeHook memaksa timestamp = Asia/Jakarta (WIB). Tidak boleh ada log dengan timezone lain.
  • Rotasi harian: logs/YYYY/MM/YYYY-MM-DD.log (writer ditutup & dibuka ulang per hari).
  • Helper field: logger.String/Int/Int64/Bool/Any/ErrorField untuk konsistensi key.
  • caller & function_name aktif otomatis ketika Environment != "production".

2.2 Metrics

  • prometheus/client_golang ter-import. Belum ada handler /metrics yang terpasang di routes — TODO sebelum production multi-instance.

2.3 Tracing

  • Field request_id (UUID) wajib di-inject melalui middleware HTTP. Untuk worker, gunakan ID dokumen yang sedang diproses (idxpesanobat, kfa_code) sebagai correlation ID.

3. Database Resilience

3.1 Connection Pool

Setiap entry databases.<name> di config.yaml wajib mendefinisikan:

max_open_conns: 25
max_idle_conns: 25
conn_max_lifetime: 5m

Jika max_open_conns tidak diatur, infrastructure menerapkan formula default (CPU_Cores * 2) + 1.

3.2 Multi-DB & Read Replica

  • Database Manager mendukung PostgreSQL, MySQL, SQL Server, SQLite, MongoDB dalam satu service.
  • CommandRepository selalu menulis ke primary; QueryRepository membaca dari replica (round-robin) jika dikonfigurasi.
  • SLOW QUERY THRESHOLD: 200 ms (GORM logger adapter); query di atas ambang ini dilog warn level dengan SQL + duration.

3.3 Query Builder (pkg/utils/query)

  • Whitelist kolom + dialect-aware (Postgres, MySQL, MSSQL).
  • Pencegahan SQL injection wajib via parameter binding — no string concat di repository.
  • Tests: sql_builder_test.go, dialects_test.go.

4. Keamanan

4.1 Secret Management

  • Semua kredensial dilarang hardcoded. Akses via env var atau Viper dari .env / .env.prod.
  • Anomali yang diketahui (patient/migrator.go:23-26): defaultUsername "adm_pendaftaran" & defaultPassword "1234". WAJIB dihapus atau dijadikan env-only sebelum file ini diaktifkan.

4.2 Auth

  • Provider pluggable: jwt, keycloak, static, hybrid (config auth.type + auth.fallback_to).
  • JWT signing key di env; Keycloak JWKS URL di env.
  • Rate limit per IP dikelola Redis (security.rate_limit.requests_per_minute, default 60).

4.3 Crypto BPJS

  • HMAC-SHA256 untuk signature (X-cons-id + & + X-timestamp).
  • Dekripsi AES-256-CBC (bpjs/crypto.go):
    • key = SHA256(ConsID + SecretKey + Timestamp)
    • IV = 16 byte pertama dari key
    • Padding PKCS7
  • Auto-decompression LZString → Gzip → plaintext (decompression.go).

4.4 SatuSehat OAuth2

  • Client-Credentials flow; token cached in-memory dengan safety margin 60 detik sebelum exp.
  • Pada 401, request retry otomatis setelah ForceRefreshAndGetToken (satusehat/client.go).
  • Mutex tokenMutex di worker.Manager mencegah race antar worker.

4.5 RBAC Caching

  • Kunci cache permission menggunakan SHA-256 dari (role_id, page_id, parameter query) — bukan plaintext.
  • Invalidate by prefix otomatis pada Create/Update/Delete.

5. Resiliensi Worker

5.1 Initial Login Retry

  • 6× percobaan dengan jeda 5 detik. Jika semua gagal → Fatal (service mati). Lihat worker.go:42-55.

5.2 Rate Limit Handling (per worker)

Worker Strategi
KFA Master Puller 30s list API, 60s detail API, 500ms antar item, idle 6h saat halaman kosong
Medication / MedicationRequest / MedicationDispense rateLimitSleep = 60s + retry dokumen yang sama (tidak skip ID)
ImagingStudy / ServiceRequest Pola serupa, time-based tracker

Deteksi rate-limit fleksibel: cek status code 429 atau substring respons ("too many requests", "rate limit", "limit exceeded", "limit pengiriman", "quota exceeded").

5.3 Token Recovery

  • Tiap worker yang memanggil API internal service-satusehat wajib:
    1. Sertakan Authorization: Bearer <token> dari TokenManager.GetAccessToken().
    2. Jika respons 401 → ForceRefreshAndGetToken lalu retry sekali.
    3. Jika refresh gagal → fallback re-login (auth.go:139-149).

5.4 Graceful Shutdown

  • Root context dengan errgroup (golang.org/x/sync/errgroup).
  • Sinyal SIGINT/SIGTERMcancel() → semua goroutine select-context exit → g.Wait().
  • Tidak boleh ada for { ... } tanpa select { case <-ctx.Done(): return; default: ... } di kode worker.

5.5 Staggered Startup

  • baseDelay = 10s antar tiap worker untuk mencegah thundering herd terhadap API gov't (worker.go:268-303).

6. State Management Worker

6.1 Tracker File (Praktik Saat Ini)

  • Lokasi: internal/worker/satusehat/<resource>/last_*.txt & internal/master/kfa/kfa_tracker.txt.
  • Format: integer ID (medication, KFA, imagingstudy) atau ISO timestamp (servicerequest radiology).
  • Mapping FHIR ID disimpan harian: mapperdata/YYYY-MM/YYYY-MM-DD.txt berformat idxpesanobat|fhir_id.

Batasan kritikal: tidak aman untuk multi-replica. Wajib dipindah ke DB / Redis untuk deployment Kubernetes (lihat Devplan Phase 2).

6.2 Sync Log

  • Setiap pengiriman → record SyncLog (request payload, response, status SUCCESS/FAILED/RATE_LIMITED, error message) tersimpan di tabel SIMRS untuk audit.

7. Standar Penulisan Kode

7.1 Linting & Format

  • go fmt mandatory (CI hook disarankan).
  • Komentar fungsi publik dalam Bahasa Indonesia diperbolehkan (codebase saat ini multilingual); konsistensi per file diutamakan.

7.2 Error Handling

  • Gunakan pkg/errors.AppError untuk error berkode (HTTP/gRPC mapping otomatis).
  • Wrapping: fmt.Errorf("konteks: %w", err) — selalu %w jika ingin di-unwrap.
  • Worker tidak boleh panic; pakai logger.Error + retry/skip.

7.3 Testing

  • File *_test.go wajib di package pkg/utils/query. Coverage modul bisnis saat ini rendah — TODO unit test layer service.

7.4 Generator Boilerplate

  • Modul baru dibuat via scripts/context.sh -s <file.sql> atau -j <file.json>.
  • Generator menghasilkan: entity, DTO, repository (Command + Query), service, mapper, gRPC proto draft.

8. Dependensi & Lisensi

  • Go runtime: 1.25 (go.mod baris 3).
  • Web: Gin 1.10, gRPC 1.78, Swagger via swaggo/swag 1.16.
  • Persistence: GORM 1.30 (postgres/mysql/sqlserver/sqlite driver), sqlx 1.4, MongoDB driver 1.17.
  • Cache & infra: redis/go-redis v9.17, MinIO Go v7.0.98, Prometheus client 1.23.
  • Crypto: golang.org/x/crypto v0.49, JWT golang-jwt v5.2.
  • Util: logrus 1.9, viper-style config via karincake/apem.
  • License: Apache 2.0 (lihat header swagger).

9. Checklist Audit Periodik

  • Semua tracker .txt masih dibutuhkan & sinkron dengan DB.
  • Tidak ada secret di repository (grep -r "password.*=.*\"" . clean).
  • logger.Default() digunakan; tidak ada fmt.Println di production path.
  • Setiap worker punya rate-limit handler + token retry.
  • Cache TTL & invalidation pattern terdokumentasi per modul.
  • Migration script idempotent.
  • Prometheus /metrics endpoint live & terkonsumsi monitoring stack.

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