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,157 @@
# 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