8.9 KiB
🛡️ 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— terpisahCommandRepository(GORM, primary) danQueryRepository(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 }TokenManagerinterface (GetAccessToken,ForceRefreshAndGetToken) — di-implement olehworker.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 didevelopment. localTimeHookmemaksa 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/ErrorFielduntuk konsistensi key. caller&function_nameaktif otomatis ketikaEnvironment != "production".
2.2 Metrics
prometheus/client_golangter-import. Belum ada handler/metricsyang 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.
CommandRepositoryselalu menulis ke primary;QueryRepositorymembaca 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(configauth.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
- key =
- 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
tokenMutexdi 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-satusehatwajib:- Sertakan
Authorization: Bearer <token>dariTokenManager.GetAccessToken(). - Jika respons 401 →
ForceRefreshAndGetTokenlalu retry sekali. - Jika refresh gagal → fallback re-login (auth.go:139-149).
- Sertakan
5.4 Graceful Shutdown
- Root
contextdenganerrgroup(golang.org/x/sync/errgroup). - Sinyal
SIGINT/SIGTERM→cancel()→ semua goroutine select-context exit →g.Wait(). - Tidak boleh ada
for { ... }tanpaselect { case <-ctx.Done(): return; default: ... }di kode worker.
5.5 Staggered Startup
baseDelay = 10santar 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.txtberformatidxpesanobat|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, statusSUCCESS/FAILED/RATE_LIMITED, error message) tersimpan di tabel SIMRS untuk audit.
7. Standar Penulisan Kode
7.1 Linting & Format
go fmtmandatory (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.AppErroruntuk error berkode (HTTP/gRPC mapping otomatis). - Wrapping:
fmt.Errorf("konteks: %w", err)— selalu%wjika ingin di-unwrap. - Worker tidak boleh panic; pakai
logger.Error+ retry/skip.
7.3 Testing
- File
*_test.gowajib di packagepkg/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/swag1.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
.txtmasih dibutuhkan & sinkron dengan DB. - Tidak ada secret di repository (
grep -r "password.*=.*\"" .clean). logger.Default()digunakan; tidak adafmt.Printlndi production path.- Setiap worker punya rate-limit handler + token retry.
- Cache TTL & invalidation pattern terdokumentasi per modul.
- Migration script idempotent.
- Prometheus
/metricsendpoint live & terkonsumsi monitoring stack.
Disusun ulang: Tim Engineering GoPrint, 2026-05-13.