# Fase 1 — Task Pack (Urutan Implementasi Langsung) Dokumen ini adalah daftar kerja yang bisa langsung dipakai sebagai urutan PR/ticket. ## Paket A — Foundation Core (Step 1) ## A.1 PR: Shared Foundation + Middleware - scope: `shared`, tracing, request/error wrapper, idempotency table baseline, audit helper - target file: - shared error formatter - request_id/trace_id generator - idempotency service CRUD/read - acceptance: - semua response punya `request_id` di body meta - idempotency write/read bisa ditest di local endpoint sample ## A.2 PR: Auth Baseline - scope: login/admin token minimal, auth middleware, role dasar - acceptance: - endpoint admin menolak tanpa token (`401`) - token valid memberi akses CRUD Step 1 ## A.3 PR: Merchant CRUD - scope: `POST /admin/merchants`, `GET /admin/merchants`, `GET /admin/merchants/{id}`, `PATCH /admin/merchants/{id}` - acceptance: - create/read/update berhasil - duplikasi create dengan idempotency key tidak membuat duplicate ## A.4 PR: Outlet + Terminal - scope: - `POST /admin/merchants/{merchantId}/outlets` - `GET /admin/outlets`, `GET /admin/outlets/{id}`, `PATCH /admin/outlets/{id}` - `POST /admin/outlets/{outletId}/terminals` - `GET /admin/terminals`, `GET /admin/terminals/{id}`, `PATCH /admin/terminals/{id}` - acceptance: - outlet/terminal berkait dengan merchant/outlet parent - error jika parent tidak valid ## A.5 PR: Device Registry + Binding - scope: - `POST /admin/devices`, `GET /admin/devices`, `GET /admin/devices/{id}`, `PATCH /admin/devices/{id}` - `POST /admin/devices/{id}/bind` - `POST /admin/devices/{id}/unbind` - acceptance: - bind menghasilkan `device_bindings` aktif tunggal - unbind menonaktifkan binding aktif ## A.6 PR: Migration + Seed Phase 1 - scope: - tables dari Step 1 MVP - seed: 2 merchant, 2 outlet, 2 terminal, 3 device - user/admin seed baseline - acceptance: - sistem startup clean dengan data seed - query dasar berjalan ## Paket B — Transaction + Webhook (Step 2) ## B.1 PR: Transaction Core & State Machine - scope: - tabel `transactions`, `transaction_events` - states: initiated, awaiting_payment, paid, failed, expired - acceptance: - create transaksi dasar - timeline event tercatat saat state berubah ## B.2 PR: Callback Receiver - scope: `POST /integrations/qris/callback` - rules: - signature validation - idempotency callback - duplicate replay handling - acceptance: - valid callback -> state paid - duplicate callback tidak mengubah state - signature salah -> 401 ## B.3 PR: Event Emission (`transaction.paid`) - scope: - emit internal event saat status bayar sukses - acceptance: - setiap successful callback menghasilkan event sekali (idempotent) ## Paket C — Notification (Step 3) ## C.1 PR: Notification Orchestrator - scope: - listen `transaction.paid` - buat `notifications` record - acceptance: - transaksi paid menghasilkan record notification ## C.2 PR: MQTT Publisher - scope: - publish ke `devices/{deviceId}/downlink/payment/success` - payload sesuai kontrak - acceptance: - publish sukses update `delivery_status=sent` - fallback jika publish gagal -> `retrying/failed` ## C.3 PR: Retry + Admin Retry API - scope: - retry loop (15/30/60) - `POST /admin/transactions/{transactionId}/retry-notification` - acceptance: - status update berjalan dari retrying ke sent/gagal ## Paket D — Device & Ops Monitoring (Step 4) ## D.1 PR: Heartbeat Ingestion - scope: - `POST /device/heartbeat` - update `devices.last_seen_at` - simpan `device_heartbeats` - acceptance: - status heartbeat dan latest heartbeat terlihat per device ## D.2 PR: Device Listing + Detail - scope: - `GET /admin/devices` - `GET /admin/devices/{id}` - derived status online/stale/offline/degraded - acceptance: - list/detail bisa difilter dan menampilkan status ## D.3 PR: Transaction List/Detail + Heartbeat History - scope: - `GET /admin/transactions`, `GET /admin/transactions/{id}` - `GET /admin/devices/{id}/heartbeats` - acceptance: - timeline event dan heartbeat history tampil ## D.4 PR: Dashboard KPI + Failed Notification View - scope: - `GET /admin/dashboard/summary` - `GET /admin/notifications/failed` - acceptance: - 5 metrik minimum tampil - daftar notifikasi failed bisa difilter ## Urutan Eksekusi Terbuka 1. A.1 → A.2 → A.6 (mendukung semua service berikutnya) 2. A.3 → A.4 → A.5 3. B.1 → B.2 → B.3 4. C.1 → C.2 → C.3 5. D.1 → D.2 → D.3 → D.4 ## Aturan Dependensi - B paket tidak boleh dimulai jika A.5 belum selesai (binding + transaksi dasar belum valid) - C paket tidak boleh dimulai jika B.3 belum siap - D paket bisa jalan paralel dengan C jika A dan B core sudah jalan ## Exit Criteria Fase 1 (siap Step 2) - [ ] static paid flow jalan end-to-end - [ ] tidak ada duplicate state via callback - [ ] notification ada untuk paid tx - [ ] device heartbeat dan status ops visible