# 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
