# 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 1–2 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 2–3 #### 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 1–4 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