Skip to main content

Firebase Service

Firebase Service adalah service notifikasi push (FCM) dan verifikasi Firebase Phone Auth untuk Kesles Merchant. Service live di production, loopback-only, dan menjadi satu-satunya pemilik Firebase Admin SDK di seluruh sistem — caller lain (core_api, dashboard_api, payment_service, marketing_service) berkomunikasi via HTTP internal.

1. Identitas Service

AtributNilai
Nama servicefirebase_service
Port8093 (loopback 127.0.0.1)
Main DBdb_kesles_merchant_notification (schema notification)
VM dir/home/enalfarid/kesles_merchant/merchant_firebase/
Binaryfirebase-service (Linux ELF amd64)
Systemd unitfirebase-service.service
Repo pathservices/firebase_service/

Firebase Admin SDK berada satu-satunya di services/firebase_service/internal/push/fcm.go. merchant_core_api tidak punya Firebase SDK; semua FCM call dari core_api lewat HTTP via merchant_core_api/internal/fcmservice/client.go ke firebase_service:8093.

2. Tanggung Jawab

  • Kirim push FCM (single + bulk) dengan auto-deactivate token saat UNREGISTERED.
  • Kelola registry push token (notification.fcm_push_tokens) — register/refresh idempotent, list per user/merchant, soft-deactivate.
  • Verifikasi Firebase ID token untuk Phone Auth (RS256 + Google JWKS) dan tulis audit ke notification.phone_verifications.
  • Broadcast push (app_update / announcement / maintenance) dengan worker dispatcher in-process.
  • Per-user-global notification preferences (opt-out, lintas merchant).
  • KPI agregat (online users, active today) untuk dashboard summary.
  • Push alert transaksi & settlement yang dipanggil payment_service.

3. Endpoint

Semua endpoint /internal/* butuh header X-Internal-API-Key (constant-time compare). /health dan /ready publik.

MethodPathAuthTujuan
GET/healthnoneLiveness
GET/readynoneReadiness — DB ping + Firebase config check
POST/internal/fcm/sendAPI keyKirim push 1 token (idempotent middleware), auto-deactivate jika UNREGISTERED
POST/internal/fcm/send-bulkAPI keyKirim push banyak token (idempotent middleware)
POST/internal/fcm/tokensAPI keyRegister / refresh push token (idempotent)
GET/internal/fcm/tokens?user_id=X / ?merchant_id=XAPI keyList token aktif per user/merchant
POST/internal/fcm/tokens/lookupAPI keyBulk lookup token by user_ids
GET/internal/fcm/tokens/activeAPI keyEnumerate token aktif (paginated) untuk audience resolver
GET/internal/fcm/tokens/deviceAPI keyKnown-device check by user_id+device_id
DELETE/internal/fcm/tokens/{push_token}API keySoft-deactivate token
GET/internal/fcm/kpiAPI keyKPI agregat online_users + active_today_users
GET/POST/dst/internal/fcm/templates · /internal/fcm/templates/{id}API keyCRUD katalog template (via dashboard_api proxy)
GET/internal/fcm/message-logsAPI keyMessage log read-only untuk panel dashboard
GET/internal/fcm/overviewAPI keyKPI overview untuk panel Firebase Overview & Health
GET/internal/fcm/send-volumeAPI keyTimeseries volume kirim untuk chart
GET/internal/fcm/provider-healthAPI keyHealth provider/platform
POST/internal/firebase-auth/verify-phone-tokenAPI keyVerifikasi Firebase ID token Phone Auth (RS256 + JWKS)
GET/PUT/internal/users/{user_id}/notification-prefsAPI keyPer-user-global opt-out (user_notification_prefs)
POST/GET/internal/broadcastsAPI keyBroadcast CRUD create / list
GET/DELETE/internal/broadcasts/{id} · /internal/broadcasts/{id}/sendsAPI keyDetail / cancel / audit log per delivery
POST/internal/push/transaction-alertAPI keyPush "Pembayaran Masuk" (dipanggil payment_service)
POST/internal/push/settlement-completeAPI keyPush "Settlement Berhasil" (dipanggil payment_service)

4. Integrasi & Routing

Firebase Admin SDK adalah single-owner di firebase_service. Caller lain memakai HTTP internal:

CallerMekanismeEndpoint yang dipakai
merchant_core_apiinternal/fcmservice/client.go (HTTP)/internal/fcm/send, /send-bulk, /tokens, /tokens/lookup, /tokens/device, /internal/firebase-auth/verify-phone-token
dashboard_apiproxy + KPI client/internal/fcm/kpi, /templates, /message-logs, /overview, /send-volume, /provider-health, /internal/broadcasts* (role gate {superadmin, admin})
payment_serviceHTTP async (fire-and-forget)/internal/push/transaction-alert, /internal/push/settlement-complete
marketing_serviceworker internal/worker/fcmclient.go (FCM_SERVICE_BASE_URL default http://127.0.0.1:8093)/internal/fcm/tokens/active, /internal/fcm/send-bulk

Broadcast push diproses oleh worker in-process (internal/worker/dispatcher.go): poll notification.fcm_broadcasts (SELECT FOR UPDATE SKIP LOCKED, status queuedsending), resolve audience (all / platform / app_version_lt / user_ids), cek user_notification_prefs, dispatch via push.Client.Send in-process, lalu finalize. Worker diaktifkan oleh BROADCAST_WORKER_ENABLED=true.

5. Konfigurasi (env)

EnvWajib (production)Keterangan
APP_ENVyaproduction di VM
APP_PORTdefault 8093
POSTGRES_DSNyaDSN db_kesles_merchant_notification
INTERNAL_NOTIFICATION_API_KEYyaShared secret X-Internal-API-Key; identik dengan caller
FIREBASE_PROJECT_IDyakesles-merchant
FIREBASE_CLIENT_EMAILyaService account Admin SDK
FIREBASE_PRIVATE_KEYyaService account private key
FIREBASE_JWKS_URLOverride DILARANG di production (fail-fast); dev only
REDIS_ADDR / REDIS_USERNAME / REDIS_PASSWORD / REDIS_DBIdempotency store; kosong → middleware no-op
BROADCAST_WORKER_ENABLEDtrue aktifkan worker broadcast (default off)

validateConfig fail-fast saat boot di production jika salah satu dari INTERNAL_NOTIFICATION_API_KEY, FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY, POSTGRES_DSN kosong, atau jika FIREBASE_JWKS_URL di-set.

6. Security Hardening (konfigurasi saat ini)

  • Internal auth: X-Internal-API-Key dibandingkan dengan subtle.ConstantTimeCompare (timing-safe). Key kosong → semua endpoint internal reject 503.
  • HTTP timeouts: ReadHeaderTimeout 5s, ReadTimeout 30s, WriteTimeout 30s, IdleTimeout 120s.
  • Body limit: maxBodySizeMiddleware membatasi body POST/PUT/PATCH maksimal 1 MB.
  • DB pool: MaxOpenConns 25, MaxIdleConns 5, ConnMaxLifetime 5m.
  • Driver: pgx/v5 via stdlib adapter (sql.Open("pgx", dsn)).
  • Idempotency: middleware Redis-backed pada /internal/fcm/send + /send-bulk (namespace idempo:fcm); fail-open jika Redis tidak reachable.
  • Logging: slog structured event (mis. fcm_send dengan taxonomy classifyFCMError), tanpa PII.
  • Graceful shutdown: SIGTERM/SIGINT memberi window in-flight request sebelum stop.

Observability — taxonomy classifyFCMError

ClassTrigger
okerr == nil
fcm_unregisteredtoken revoked / app uninstalled
fcm_authHTTP 401/403 — masalah kredensial service account
fcm_quotaHTTP 429 — FCM rate limit
fcm_5xxHTTP 5xx — FCM transient
fcm_4xxHTTP 4xx lain
fcm_oauthtoken endpoint gagal
network_timeouterror timeout/deadline/i/o
networkerror dial/connection/tls/no such host
not_configuredkredensial kosong
unknownfallback

7. Database (schema notification di db_kesles_merchant_notification)

TabelFungsi
fcm_push_tokensSole source of truth registry push token. Tenant-aware (tenant_id), tanpa FK cross-DB
phone_verificationsAudit verifikasi Phone Auth (append-only, best-effort)
fcm_broadcasts + fcm_broadcast_sendsBroadcast + delivery log, UNIQUE (broadcast_id, user_id) idempotency
user_notification_prefsOpt-out per-user-global lintas merchant (beda dengan merchant.merchant_user_notification_prefs per-merchant per-event)

8. VM Deployment

AtributNilai
Host VMkesles-merchant
Folder/home/enalfarid/kesles_merchant/merchant_firebase/
Binaryfirebase-service
Systemd unitfirebase-service.service
Port127.0.0.1:8093 (loopback)
Logsjournalctl -u firebase-service.service

9. Referensi

DokumenIsi
architecture.mdDesain endpoint + payload contract + observability
sms-otp-service-plan.mdDetail Phone Auth (Firebase verifier)
console-operator-setup.mdSetup operator Firebase Console
polqo-migration-plan.mdRencana migrasi Polqo (deferred)