Initial commit

This commit is contained in:
2026-05-25 08:22:12 +07:00
commit a152c99cce
154 changed files with 39033 additions and 0 deletions

View File

@ -0,0 +1,510 @@
# Implementation Roadmap - QRIS Soundbox Platform v1
## 1. Prinsip Delivery
- kerjakan fondasi domain lebih dulu
- prioritaskan flow yang paling cepat memberi nilai bisnis
- buat modul yang bisa dipakai ulang untuk static, dynamic MQTT, dan dynamic API
- selesaikan admin visibility lebih awal untuk membantu operasi
## 2. Fase 0 - Persiapan Pra-Pelaksanaan
### Tujuan
menyelaraskan fondasi teknis, governance, dan alur kerja supaya pembangunan fase berikutnya stabil dan konsisten
### Deliverable Awal
- Tim dan role pelaksana disepakati (PO, Tech Lead, Backend, Infra, QA, Ops)
- Definisi source control workflow dan branching strategy
- CI/CD base pipeline siap (build, lint, security scan dasar)
- Lingkungan dev/test/staging dipastikan terpisah
- Standar kontrak siap pakai:
- API contract final v1
- MQTT topic dan payload final v1
- schema migration baseline
- Skema status, kode error, dan idempotency key standar disepakati
- Definisi tracing & logging baseline (request_id, trace_id, event_id, correlation_id)
- Definition of Done (DoD) tim sinkron untuk tiap fase
### Setup Operasional
- Issue tracker dan sprint board aktif
- Template ticket siap (story, acceptance criteria, checklist testing)
- Test environment data seed untuk merchant, outlet, terminal, device baseline
- Device simulator untuk static + MQTT-only + API-direct
- Monitoring awal:
- uptime endpoint
- callback receiver readiness check
- MQ publish/subscribe smoke test
### Risiko Persiapan
- Scope creep pada Fase 0 -> batasi sampai API/MQTT contract dan baseline infrastruktur
- Ketidaksinkronan data model -> gunakan satu schema owner untuk review harian
- Keterlambatan perangkat test -> sediakan mock/simulator lebih awal
- Akses keamanan belum stabil -> pastikan IAM/token policy baseline sebelum endpoint sensitive dibuka
### DoD Fase 0
- [ ] semua dokumen kontrak dan skema siap untuk implementasi
- [ ] repositori, pipeline, dan environment awal siap dipakai
- [ ] template sprint dan ticket aktif
- [ ] device simulator bisa mensimulasikan callback dan heartbeat
- [ ] tim siap masuk Fase 1 tanpa menunggu keputusan besar
## 3. Fase 1 - Foundation MVP
### Tujuan
mengaktifkan merchant, device registry dasar, callback payment, dan static soundbox notification
### Scope
- merchant registry dasar
- outlet dan terminal management dasar
- device registry/TMS dasar
- device binding
- callback/webhook receiver
- transaction registry
- notification service dasar
- MQTT push basic
- admin dashboard basic
- transaction monitoring basic
### Output
- static soundbox flow berjalan end-to-end
- admin dapat melihat merchant, device, transaksi, status notif
### Breakdown Implementasi Fase 1
#### Sprint 1 — Auth & Core Platform
- Setup repo struktur service dan pipeline
- Setup observability dasar (request_id/trace_id, structured log)
- Setup RBAC baseline untuk admin dan service-to-service auth
- Setup auth device token + rotation policy awal
- Setup migrasi awal sesuai schema MVP
- Endpoint onboarding merchant basic (`/admin/merchants` CRUD minimal)
- Endpoint outlet dan terminal basic (`/admin/merchants/{merchantId}/outlets`, `/admin/outlets/{outletId}/terminals`)
- Kriteria Selesai: data merchant/outlet/terminal bisa dibuat, diupdate, ditampilkan, dan dihapus sesuai kebutuhan flow
#### Sprint 2 — Device Foundation & Binding
- Endpoint device registry (`/admin/devices` CRUD)
- Endpoint konfigurasi awal device (`/admin/devices/{deviceId}/bind`, `/unbind`)
- Simpan binding aktif ke merchant, outlet, terminal dengan history
- Endpoint heartbeat device (`/device/heartbeat`) + tabel `device_heartbeats`
- Endpoint get device dan list heartbeat untuk ops
- Status device derived: online/stale/offline (berdasarkan `last_seen_at`)
- Kriteria Selesai: device bisa didaftarkan, di-bind, kirim heartbeat, dan terlihat statusnya di dashboard ops
#### Sprint 3 — Transaction Engine + Webhook Static
- Model transaksi inti untuk mode static (`transactions` + `transaction_events`)
- Webhook callback (`/integrations/qris/callback`) dengan verifikasi signature
- Idempotency key untuk callback dan penanganan duplicate callback
- State machine transaksi minimal: `initiated`, `paid`, `failed`, `expired`
- Audit dasar pada perubahan status transaksi
- Kriteria Selesai: callback memutakhirkan status transaksi dan terekam eventnya
#### Sprint 4 — Notifikasi Berbasis MQTT
- Event notification orchestrator sederhana dari status transaksi `paid`
- Publisher ke topic device `devices/{deviceId}/downlink/payment/success`
- Format payload sesuai kontrak MQTT draft
- Tabel `notifications` + status pengiriman (`queued/sent/acknowledged/failed`)
- Retry basic untuk status gagal dengan backoff sederhana (tanpa DLQ penuh di sprint ini)
- Kriteria Selesai: transaksi static memicu notifikasi sukses ke device yang terikat
#### Sprint 5 — Admin Monitoring & Readiness
- Admin transaction list + detail (`/admin/transactions`, `/admin/transactions/{transactionId}`)
- Admin device/merchant list dasar
- Admin dashboard KPI minimal (tx hari ini, success rate, device online, pending notif)
- Endpoint retry notifikasi (`/admin/transactions/{transactionId}/retry-notification`)
- Monitoring kegagalan callback dan notifikasi
- Kriteria Selesai: alur static end-to-end terlihat utuh di admin (input callback -> status tx -> notif -> ack/failed)
#### Acceptance Criteria Fase 1
- Static QR flow end-to-end berjalan untuk minimal 1 merchant dan 1 device
- Callback duplicate tidak menambah transaksi ganda
- transaksi yang berhasil bayar tercatat `paid` dan membuat ledger entry placeholder
- status device `online` tersimpan saat heartbeat berhasil
- notifikasi sukses terkirim dengan event_id
- audit log mencatat aksi CRUD penting dan callback state changes
#### Dependency Diagram (Ringkas)
- Auth & Core dibutuhkan sebelum semua API/device flow
- Device Binding dibutuhkan sebelum transaksi menargetkan device
- Webhook dipasang sebelum notifikasi payment
- Notifikasi MQTT dipasang setelah transaction status `paid` stabil
- Admin monitoring dipasang setelah data transaksi dan notification pipeline berfungsi
#### Risiko Awal & Mitigasi (Fase 1)
- Mapping merchant-transaksi-device salah -> hard binding + validasi binding aktif saat kirim notifikasi
- Callback retry menyebabkan duplicate -> key composite pada partner reference + event idempotent check
- Device offline saat notify -> queue retry + status `retrying`
- Data konsistensi merchant/outlet/terminal tidak stabil -> blokir pembuatan transaksi jika binding tidak valid
- Audit minim -> tambahkan actor/action/entity id di setiap state mutasi penting
#### Definisi Selesai Fase 1
- [ ] static flow: scan-pay callback sukses -> transaksi `paid` -> notifikasi success diterima
- [ ] dashboard ops melihat transaksi, merchant, device, notification status
- [ ] retry basic untuk callback dan notification tersedia
- [ ] skenario utama: normal, duplicate callback, device tanpa binding, webhook invalid signature, device offline
## 4. Fase 2 - Dynamic QR Enablement
### Scope
- QRIS dynamic orchestration
- MQTT uplink request flow
- API direct create QR flow
- capability resolver
- heartbeat dan online status
- config management dasar
### Output
- support 3 jenis device flow
- dynamic QR bisa berjalan melalui MQTT-only dan API-direct
### Breakdown Implementasi Fase 2
#### Sprint 1 — Capability & Routing
- Implementasi capability profile pada `devices.capability_profile_json`
- Resolver untuk menentukan flow:
- `STATIC` device: tidak boleh create QR
- `DYNAMIC_MQTT` device: create via MQTT request
- `DYNAMIC_API` device: create via API langsung
- Middleware validasi capabilty dan izin per endpoint/action
- Kriteria Selesai: request invalid akan reject dengan error yang jelas (`DEVICE_CAPABILITY_NOT_SUPPORTED`, `DEVICE_NOT_BOUND`)
#### Sprint 2 — API-direct Dynamic QR
- Finalisasi endpoint `POST /device/transactions/dynamic-qr`
- Validasi payload: `amount`, `terminal_id`, `request_id`, device binding, capabilty
- Idempotency handling pada request device (idempotency key / request_id)
- Orchestrator QRIS dynamic:
- panggil partner QRIS
- simpan `transactions` status `awaiting_payment`
- set `transaction_events`
- Response standard:
- `transaction_id`, `qr_payload`, `expires_at`, `status`, `request_id`
- Kriteria Selesai: device API mendapatkan QR dinamis dan dapat memantau status pembayaran via callback
#### Sprint 3 — MQTT Dynamic Uplink/Downlink
- Implementasi handler uplink MQTT untuk request:
- `devices/{deviceId}/uplink/dynamic-qr/request`
- Mapping `request_id` -> `correlation_id` untuk response
- Publish response ke:
- `devices/{deviceId}/downlink/dynamic-qr/response`
- Idempotent request handling untuk MQTT retry
- Kriteria Selesai: device MQTT-only bisa membuat QR sukses minimal untuk normal flow
#### Sprint 4 — Heartbeat & Status Online yang Lebih Akurat
- Peningkatan endpoint heartbeat:
- `POST /device/heartbeat` + MQTT heartbeat ingest terstandar
- health score dari `network_strength`, `battery_level`, `last_seen_at`
- Derivasi status:
- `online`, `degraded`, `stale`, `offline`
- Filter admin untuk status dan rentang health metric
- Kriteria Selesai: ops bisa memfilter device berdasarkan health dan mengurangi retry pada kondisi degraded
#### Sprint 5 — Konfigurasi Device Dasar
- Endpoint config:
- `GET /device/config`
- `POST /device/config/ack`
- Command config push via MQTT:
- `devices/{deviceId}/downlink/config/push`
- Versioned config (`config_version`) dan idempotent ACK
- Kriteria Selesai: perubahan config tidak memutus flow pembayaran dan bisa disinkronkan ulang
#### Acceptance Criteria Fase 2
- 3 mode device berfungsi:
- static: hanya notifikasi
- dynamic-MQTT: request dan response QR via broker
- dynamic-API: request dan response via API
- duplikasi request tidak membuat transaksi ganda
- setiap request punya korelasi penuh `request_id/correlation_id`
- callback tetap jadi sumber truth status bayar
- notifikasi sukses tetap melalui MQTT dengan payload terstandar
#### Dependency Diagram (Ringkas)
- Fase 2 dimulai setelah Fase 1 merchant/device/binding dan callback stabil
- API-direct bisa mulai setelah capability resolver dan transaksi core siap
- MQTT uplink membutuhkan MQTT adapter dan auth device yang siap dari Fase 1
#### DoD Fase 2
- [ ] Fitur create dynamic QR untuk API dan MQTT berfungsi
- [ ] dynamic-qr request/reply korelatif dan idempotent
- [ ] heartbeat/status device dipakai untuk operasional dan retry
- [ ] config push/ack dasar berjalan
- [ ] semua path mencatat trace/request IDs konsisten
## 5. Fase 3 - Finance Core
### Scope
- ledger entries
- merchant payable
- fee engine
- settlement batch
- payout/disbursement
- settlement monitoring
- reconciliation basic
### Output
- merchant balance dan settlement dapat dihitung dan dibayarkan
### Breakdown Implementasi Fase 3
#### Sprint 1 — Ledger Foundation
- Finalisasi skema `ledger_entries` dan index query balance
- Implementasi akun per-merchant saldo running (materialized atau computed-on-read)
- Masukkan entri ledger saat transaksi berubah ke `paid`:
- `gross_income`
- `platform_fee`
- `merchant_payable`
- Integrasi reconciliation placeholder agar entri ledger bisa ditandai `reconciled=false`
- Kriteria Selesai: setiap transaksi sukses menambah entri ledger yang benar
#### Sprint 2 — Fee Engine
- Mapping fee profile per merchant (fixed + percentage jika berlaku)
- Formula payout per transaksi:
- `merchant_payable = gross - fee`
- Validasi konsistensi nilai (rounding, precision uang)
- Simpan audit metadata fee calculation
- Kriteria Selesai: perubahan fee profile langsung memengaruhi simulasi payable
#### Sprint 3 — Settlement Batch
- Buat job pembuat settlement periodik (harian/mingguan/period custom)
- Generate `settlements` dan `settlement_items`
- Auto-status: draft -> ready_to_pay -> paid / failed
- API basic:
- `POST /admin/settlements/run`
- `GET /admin/settlements`
- `GET /admin/settlements/{settlementId}`
- Kriteria Selesai: batch untuk periode tertentu bisa dibuat dan diekspor
#### Sprint 4 — Disbursement/Payout
- Implementasi eksekusi payout via connector bank/disbursement
- Simpan `payout_attempts` (attempt, payload, response, status)
- Retry payout dasar + endpoint retry payout
- Fallback status jika payout gagal / pending
- Kriteria Selesai: payout attempt sukses atau tercatat gagal dengan alasan terstruktur
#### Sprint 5 — Monitoring Finance Dasar
- Dashboard settlement: gross, fee, net, status payout
- Reconciliation basic:
- compare internal `gross/net` vs feed partner
- status `matched`, `mismatch`, `missing_internal`, `missing_external`
- Kriteria Selesai: perbedaan finansial terlihat dan bisa di-escalate
#### Acceptance Criteria Fase 3
- saldo merchant dapat dihitung dari transaksi settled
- settlement batch dan payout tidak bergantung pada notifikasi device
- failed payout tidak menghapus transaksi dan tetap terjaga jejaknya
- fitur finance dapat dijalankan dengan idempotency dasar
#### Dependency Diagram (Ringkas)
- Bergantung penuh pada Fase 12 untuk transaction lifecycle + terminal/merchant/terminal binding
- Fee engine perlu fee profile dan transaksi yang valid
- Payout memerlukan settlement batch dan reconciliation record yang konsisten
#### DoD Fase 3
- [ ] ledger entries otomatis terbentuk saat transaksi paid
- [ ] settlement batch bisa dibuat, dipreview, dan dieksekusi
- [ ] payout attempt dan status payout terekam
- [ ] laporan mismatch reconciliation dasar tersedia
- [ ] audit log menutup operasi finance kritis
## 6. Fase 4 - Operations Hardening
### Scope
- alerting
- audit log lengkap
- command center device
- duplicate suppression matang
- retry policies formal
- reconciliation exception handling
- role-based access matang
### Output
- sistem siap dioperasikan dengan volume lebih tinggi
### Breakdown Implementasi Fase 4
#### Sprint 1 — Audit & Governance
- Audit log lengkap pada aksi kritis:
- onboarding approve/reject
- binding/unbinding device
- Capture `before_json` dan `after_json`
- Searchable audit view dengan filter actor/entity/action/time
- Kriteria Selesai: perubahan konfigurasi penting dapat ditelusuri 1 klik
#### Sprint 2 — Alerting & Observability
- Alert dasar:
- callback failure rate naik
- notification failed spike
- heartbeat timeout massal
- payout failed beruntun
- Integrasi dashboard metrics dasar + error budget sederhana
- Kriteria Selesai: alert operasional muncul ke channel ops
#### Sprint 3 — Retry & Duplicate Suppression Matang
- Idempotency layer diperluas:
- callback
- dynamic QR request
- MQ downlink
- Retry policy configurable per class event
- DLQ / dead-letter untuk kegagalan permanen
- Kriteria Selesai: event gagal tidak membeku dan dapat ditindaklanjuti
#### Sprint 4 — Device Command Center
- Endpoint command:
- `POST /admin/devices/{deviceId}/commands`
- track ack melalui `device_commands`
- Command push via MQTT
- Retry command terbatas + timeout handling
- Kriteria Selesai: ops bisa mengirim perintah tes/diagnostic
#### Sprint 5 — Security & RBAC Matang
- RBAC matrix admin ops / finance / support
- Audit permission perubahan role
- Peningkatan token/device auth (exp, rotasi, revocation)
- Kriteria Selesai: akses sesuai prinsip least privilege
#### Acceptance Criteria Fase 4
- kejadian kritis punya jejak audit lengkap
- sistem lebih stabil pada kondisi gagal sementara
- device command operasional tersedia
- kontrol akses sesuai tugas/otoritas
#### Dependency Diagram (Ringkas)
- Audit dan RBAC dimulai paralel, paling optimal setelah model user-role stabil
- Alerting memerlukan observability baseline dari phase sebelumnya
- Retry matang mengunci keandalan Fase 23
#### DoD Fase 4
- [ ] audit log searchable dan immutable
- [ ] alert operasional aktif untuk skenario kegagalan utama
- [ ] duplicate suppression menutup 95% replay issue normal
- [ ] command center mencatat status end-to-end
- [ ] role permission change tervalidasi dan tercatat
## 7. Fase 5 - Merchant Experience
### Scope
- merchant portal
- merchant transaction view
- merchant settlement view
- device visibility untuk merchant
- support/help flow
### Output
- merchant bisa self-serve melihat transaksi, settlement, dan device miliknya
### Breakdown Implementasi Fase 5
#### Sprint 1 — Portal Dasar
- `GET /merchant/me`, `GET /merchant/dashboard/summary`
- Tabel transaksi dan settlement merchant
- Akses terbatas ke entitas milik merchant
- Kriteria Selesai: merchant dapat login dan melihat saldo/riwayat dasar
#### Sprint 2 — Transaction Detail & Device Visibility
- Detail transaksi merchant (status timeline + raw callback summary)
- Tabel device merchant, status online, last seen
- Pembatasan data per tenant/merchant
- Kriteria Selesai: merchant bisa menyaring sendiri transaksi/perangkatnya
#### Sprint 3 — Settlement & Support
- Halaman settlement history + settlement detail
- Informasi payout status dan retry reason
- Support center untuk tiket/FAQ awal
- Kriteria Selesai: merchant bisa memantau proses pencairan
#### Sprint 4 — Self-Serve Preferences
- Pengaturan notifikasi merchant dan outlet/terminal sederhana
- Delegasi role akses team merchant
- Kriteria Selesai: pengelolaan akun merchant lebih mandiri
#### Acceptance Criteria Fase 5
- merchant self-serve tidak bergantung pada ops untuk data transaksi normal
- hak akses tenant kuat, tidak bocor ke merchant lain
- settlement & device informasi cukup untuk operasional harian merchant
#### Dependency Diagram (Ringkas)
- Fase 5 menunggu Fase 14 untuk data transaksi, settlement, binding, audit, dan RBAC
- Fitur support berjenjang setelah data core stabil
#### DoD Fase 5
- [ ] merchant login dan melihat dashboard, transaksi, settlements
- [ ] tenant isolation valid di semua query merchant
- [ ] device visibility dan riwayat pembayaran sesuai tenant
- [ ] dokumentasi onboarding pengguna internal merchant siap dipakai
## 8. Rekomendasi Urutan Pengerjaan Tim
1. finalisasi entity dan schema awal
2. finalisasi API dan MQTT contract
3. bangun admin/tms/transaction monitoring dasar
4. bangun static notification flow
5. bangun dynamic QR flows
6. bangun ledger dan settlement
7. bangun merchant portal
## 9. Execution Now (Tanpa Jadwal)
### Fase 0 — Segera Dijalankan Hari Ini
- finalisasi dokumen API contract dan MQTT contract ke versi stabil untuk coding
- finalize ownership field API: siapa yang maintain `merchant`, `transaction`, `device`, `ledger`, `settlement`
- finalisasi error code standar dan mapping HTTP status
- buat branch awal `feat/phase-0` dan template commit message
- siapkan repositori pipeline baseline untuk lint/build/test smoke
- setup environment list: dev, staging, production target
- siapkan dataset seed:
- minimal 2 merchant
- minimal 2 outlet dan terminal
- minimal 3 device: static, dynamic-mqtt, dynamic-api
- siapkan MQTT broker topik minimal:
- `devices/{deviceId}/downlink/payment/success`
- `devices/{deviceId}/uplink/dynamic-qr/request`
- `devices/{deviceId}/downlink/dynamic-qr/response`
- `devices/{deviceId}/downlink/config/push`
- simpan semua hasil keputusan di `DECISIONS_LOG.md` (buat file baru nanti)
### Fase 1 — Langkah Eksekusi Urutan Langsung
#### Step 1 — Core Foundation
- setup service skeleton sesuai arsitektur layer
- implement RBAC baseline admin + device auth
- implement migrasi DB awal untuk merchant, outlet, terminal, device, binding, transaksi, notifications
- implement `request_id`, `trace_id`, `event_id` generator standar
- buat endpoint create/get/list merchant
- buat endpoint create/get/list outlet dan terminal
- buat endpoint binding device (bind/unbind)
- acceptance: CRUD merchant/device/terminal bisa dipakai dari admin
#### Referensi Step 1 Detail
- gunakan [12-fase1-step1-core-foundation-spec.md](/home/wira/work/codex/qris-soundbox-platform/12-fase1-step1-core-foundation-spec.md) untuk API detail, schema, dan acceptance per paket
- keputusan teknis wajib mengikuti [DECISIONS_LOG.md](/home/wira/work/codex/qris-soundbox-platform/DECISIONS_LOG.md)
#### Step 2 — Callback dan State Transaction
- implement webhook callback `/integrations/qris/callback` dengan signature check
- implement idempotency callback dan event store `transaction_events`
- implement state machine transaksi minimal
- simpan data callback raw di event
- acceptance: duplicate callback tidak duplikasi state akhir
#### Referensi Step 2 Detail
- gunakan [13-fase1-step2-callback-transaction-spec.md](/home/wira/work/codex/qris-soundbox-platform/13-fase1-step2-callback-transaction-spec.md) untuk validasi event, idempotency callback, dan state machine
#### Step 3 — Static Notification
- implement notification orchestrator pada state `paid`
- implement publish MQTT success ke device target
- simpan delivery state dan retry sekali-dua kali
- implement endpoint retry notification admin
- acceptance: static flow menghasilkan notifikasi sukses ke device bound
#### Referensi Step 3 Detail
- gunakan [14-fase1-step3-notification-spec.md](/home/wira/work/codex/qris-soundbox-platform/14-fase1-step3-notification-spec.md) untuk event flow, payload, status retry, dan endpoint retry
#### Step 4 — Device & Ops Monitoring
- implement heartbeat endpoint dan status derivation
- implement admin list device, transaction, merchant + detail basic
- implement dashboard KPI minimal
- acceptance: operator bisa melihat health device, transaksi hari ini, dan notifikasi pending
#### Referensi Step 4 Detail
- gunakan [16-fase1-step4-monitoring-spec.md](/home/wira/work/codex/qris-soundbox-platform/16-fase1-step4-monitoring-spec.md) untuk endpoint heartbeat, status derivation, KPI dashboard, dan retry-notification
### Cara Mulai Kode Hari Pertama (Checklist)
- [ ] buat modul `shared` untuk idempotency + tracing + error format
- [ ] buat modul `auth` untuk admin dan device token
- [ ] buat modul `merchant` dan `location` (outlet/terminal) terlebih dulu
- [ ] buat modul `device` dan binding service
- [ ] buat modul `transaction` state machine dan callback handler
- [ ] buat modul `notification` publisher MQTT
- [ ] buat modul `monitoring` KPI dasar admin
- [ ] verifikasi Fase 1 DoD sebelum lanjut Fase 2
- [ ] ikuti urutan kerja di [17-fase1-implementation-task-pack.md](/home/wira/work/codex/qris-soundbox-platform/17-fase1-implementation-task-pack.md)
### Aturan Kerja Eksekusi
- jangan buka perangkat lain jika API contract belum final
- jangan lanjut dynamic QR sebelum callback + static notification stabil
- setiap PR harus menyertakan:
- skenario happy path
- 1 edge case
- 1 idempotency case