# Fase 1 — Step 1: Core Foundation (Spesifikasi Implementasi) Dokumen ini memecah Step 1 menjadi paket kerja per service, API, schema, dan acceptance detail agar bisa langsung jadi ticket development. ## 1) Service yang Dibangun Dulu (Urutan Implementasi) 1. `shared` — tracing, idempotency key store, error envelope, request context 2. `identity` — admin auth + device auth + RBAC baseline 3. `merchant` — merchant onboarding dasar 4. `location` — outlet dan terminal 5. `device-tms` — registrasi device dan binding 6. `core-db` — migrasi schema MVP + seed data 7. `ingress` — endpoint admin yang membutuhkan service di atas ## 2) Kontrak Data dan ID Standard ### 2.1 ID - `merchant_id`, `outlet_id`, `terminal_id`, `device_id`, `binding_id`, `transaction_id`, `notification_id` - format rekomendasi: ULID/UUID v4 ### 2.2 Standard Trace/Event - Setiap request HTTP dan MQTT message harus membawa: - `request_id` (wajib di inbound entry API / webhook / mqtt) - `trace_id` (inherit antar service) - `event_id` (untuk emission / audit event) ### 2.3 Idempotency - Table `idempotency_keys` baru: - `id` - `scope` (`merchant_create`, `outlet_create`, `terminal_create`, dll) - `key` (unique) - `response_hash` - `created_at`, `expires_at` - Rule: hit yang sama + key sama => response deterministic dari cache/replay. ## 3) Skema DB (MVP Step 1) — Detail Migrasi ### 3.1 Tabel Inti yang Harus Ada - `merchants` - `outlets` - `terminals` - `devices` - `device_bindings` - `device_heartbeats` - `transactions` - `transaction_events` - `notifications` - `audit_logs` - `users` - `roles` - `idempotency_keys` (tambah) ### 3.2 Field Wajib Step 1 per Tabel #### `merchants` - id, merchant_code, legal_name, brand_name - status, onboarding_status - settlement_account_reference, settlement_account_type, fee_profile_id - created_at, updated_at #### `outlets` - id, merchant_id(FK), outlet_code, name, address, status - created_at, updated_at #### `terminals` - id, outlet_id(FK), terminal_code, qr_mode, partner_reference, status - created_at, updated_at #### `devices` - id, device_code, serial_number, vendor, model - communication_mode, capability_profile_json, auth_method, status - last_seen_at, firmware_version - created_at, updated_at #### `device_bindings` - id, device_id(FK), merchant_id(FK), outlet_id(FK), terminal_id(FK) - active_flag, bound_at, unbound_at - unique index: (`device_id`, `active_flag` where active_flag=true) #### `device_heartbeats` - id, device_id(FK), received_at - network_strength, battery_level, firmware_version, state, payload_json #### `transactions` - id, transaction_code, merchant_id(FK), outlet_id(FK), terminal_id(FK), device_id(FK) - qr_mode, initiation_mode, partner_reference, amount, currency, status, created_at, paid_at, expired_at, updated_at #### `transaction_events` - id, transaction_id(FK), event_type, source, payload_json, created_at #### `notifications` - id, transaction_id(FK), device_id(FK), delivery_channel, payload_type - delivery_status, retry_count, ack_status, sent_at, ack_at #### `audit_logs` - id, actor_type, actor_id, action, entity_type, entity_id - before_json, after_json, source_ip, created_at #### `users` / `roles` (minimal) - users: id, name, email, password_hash, role_id, status, created_at - roles: id, name, permissions_json, created_at ### 3.3 Index Prioritas Step 1 - `device_bindings(device_id, active_flag)` - `transactions(partner_reference)` - `transactions(merchant_id, created_at)` - `transactions(status, created_at)` - `notifications(device_id, delivery_status)` - `device_heartbeats(device_id, received_at)` - `audit_logs(entity_type, entity_id, created_at)` ## 4) Modul API Step 1 (Spesifikasi Ringkas) ### 4.1 Admin/Auth - `POST /auth/login` (bila auth service belum ada, temporary token stub boleh pakai untuk sprint 1) - `POST /auth/token/refresh` (opsional) - Validasi RBAC untuk endpoint admin: - `admin` minimal bisa akses semua CRUD Fase 1 - Error standar: - `UNAUTHORIZED`, `FORBIDDEN`, `VALIDATION_ERROR` ### 4.2 Merchant - `POST /admin/merchants` - body: - `legal_name`, `brand_name`, `settlement_account_reference`, `settlement_account_type`, `fee_profile_id` - `settlement_account_type` contoh: `merchant_virtual_account`, `merchant_bank_account`, `partner_payout_reference` - `payout_mode` (opsional): `merchant_direct` (default), `manual` - `merchant_direct` = payout diarahkan via reference payout merchant - `manual` = pencairan dibantu operasional, belum otomatis - validasi: `legal_name` required - idempotency: `Idempotency-Key` optional untuk create - `GET /admin/merchants` - `GET /admin/merchants/{merchantId}` - `PATCH /admin/merchants/{merchantId}` - `DELETE /admin/merchants/{merchantId}` (opsional; bisa soft delete via status=inactive) ### 4.3 Outlet - `POST /admin/merchants/{merchantId}/outlets` - `GET /admin/outlets` - `GET /admin/outlets/{outletId}` - `PATCH /admin/outlets/{outletId}` ### 4.4 Terminal - `POST /admin/outlets/{outletId}/terminals` - `GET /admin/terminals` - `GET /admin/terminals/{terminalId}` - `PATCH /admin/terminals/{terminalId}` ### 4.5 Device & Binding - `POST /admin/devices` - `GET /admin/devices` - `GET /admin/devices/{deviceId}` - `PATCH /admin/devices/{deviceId}` - `POST /admin/devices/{deviceId}/bind` - body: `{ merchant_id, outlet_id, terminal_id }` - rule: endpoint ini membuat record `device_bindings` baru dan menonaktifkan binding aktif lama - `POST /admin/devices/{deviceId}/unbind` - body: `{ reason }` ## 5) Acceptance Criteria per Paket ### 5.1 Merchant/Location - merchant, outlet, terminal bisa dibuat, diubah, list, detail - semua response memuat `request_id` - duplikasi create request dengan idempotency key yang sama menghasilkan resource yang sama ### 5.2 Device Binding - bind mengikat hanya satu binding aktif/device pada saat yang sama - unbind membuat binding aktif jadi nonaktif dan merekam `unbound_at` - binding referensi invalid menyebabkan endpoint device/transaction terkait ditolak di tahap berikutnya ### 5.3 Observability/Platform - semua response error mengikuti envelope: - `code`, `message`, `details`, `request_id` - log audit tersimpan saat create/update pada merchant, device, bind/unbind ### 5.4 Operasional - `last_seen_at` device berubah saat heartbeat valid (step 2 nantinya lebih lengkap) - pipeline dasar bisa menjalankan 10 request bersamaan tanpa crash (smoke test) ## 6) Definisi File/Artefak ### 6.1 Yang Harus Dibuat di Step 1 - `12-fase1-step1-core-foundation-spec.md` (dokumen ini) - `DECISIONS_LOG.md` (dibuat bersama) - migration file untuk tabel Step 1 - endpoint handlers sesuai list di atas - seed file: - 2 merchant - 2 outlet + 2 terminal - 3 devices (static, dynamic-mqtt, dynamic-api) ### 6.2 Testing Wajib (manual smoke, tanpa alat tambahan) - login/admin auth - CRUD merchant - CRUD outlet/terminal - bind/unbind device - seed device bisa dilihat di GET list ## 7) Handover ke Step 2 Step 2 tidak dimulai sampai: - endpoint binding dan auth stabil - transaksi memiliki struktur minimal `transactions + transaction_events` - event/error format terstandardisasi - idempotency baseline aktif