# BLUEPRINT FINAL — MYINFO v1.2

**Status:** BASELINE / SOURCE OF TRUTH  
**Platform:** Android Native + PHP/MySQL  
**Backend/Admin:** PHP 8.x + MySQL + Bootstrap 5  
**Frontend:** Android Native Kotlin  
**Target distribusi:** Google Play Store, diarahkan dari website resmi  
**Dokumen:** Blueprint v1.2

---

## 1. Product Definition

Nama kerja: **MyInfo**  
Nama branding sementara: **MyInfo ID**  
Descriptor sementara: **Wilayah, Bank & Informasi Indonesia**

MyInfo adalah platform informasi publik Indonesia dengan **dua jalur produk yang dipisahkan secara tegas**:

1. **MyInfo Android APK** untuk pengguna aplikasi.
2. **Commercial Data API** untuk client/developer eksternal berbayar.

MyInfo Android v1 berfokus pada dua modul:

1. Data Wilayah Indonesia
2. Data Bank dan Cabang Bank

Commercial Data API menggunakan sumber data master yang sama, tetapi memiliki authentication, quota, rate limit, API key, client, usage, dan billing foundation yang **terpisah total dari login APK**.

Arsitektur harus memungkinkan penambahan modul baru di masa depan, misalnya jadwal kereta, transportasi, direktori layanan, dan informasi publik lain, tanpa membongkar fondasi aplikasi.

---

## 2. Scope MyInfo v1

### 2.1 Modul Wilayah

Menyediakan:

- Provinsi
- Kabupaten/Kota
- Kecamatan
- Kelurahan/Desa
- Kode Provinsi
- Kode Kabupaten/Kota
- Kode Kecamatan
- Kode Kelurahan
- Kode Pos
- Search real-time
- Browse bertingkat
- Copy
- Share
- Favorite

Hierarki kode:

```text
Provinsi    31
Kab/Kota    3171
Kecamatan   317102
Kelurahan   3171021001
Kode Pos    [langsung di tbl_kelurahan]
```

Semua kode disimpan sebagai `VARCHAR`.

### 2.2 Modul Bank

Menyediakan:

- Bank terdaftar OJK
- Kode Bank
- Nama Bank
- Nama Singkat
- SWIFT Code
- Kepemilikan
- Jenis/Type Bank
- Cabang
- Kode Cabang
- Nama Cabang
- Type kantor: KPO, KCU, KCP, KK
- Alamat
- Relasi ke master wilayah
- Plus Code
- Latitude
- Longitude
- Embedded Google Map
- Nearby Bank
- Search
- Filter Bank
- Filter Wilayah
- Filter Type
- Copy
- Share
- Favorite

ATM belum masuk scope v1.

---

## 3. Out of Scope v1

Belum termasuk:

- Jadwal kereta
- Transportasi lain
- ATM directory
- Cloud sync Favorite
- Cloud sync Search History
- Background location
- Contacts
- SMS reading
- Call log
- Automatic phone-number reading
- Social features
- User-generated correction/reporting

---

## 4. Existing Database Policy

### 4.1 Database Master Sudah Ada di Hosting

Database master Wilayah dan Bank **sudah tersedia di hosting dan dianggap authoritative source**.

Project MyInfo **tidak boleh membuat ulang, mengganti, menghapus, atau menormalisasi ulang** tabel master existing tanpa instruksi eksplisit.

Master existing yang digunakan:

```text
tbl_propinsi
tbl_kabkota
tbl_kecamatan
tbl_kelurahan

tbl_bank
tbl_cabang
```

### 4.1A Approved Physical Table Mapping — 2026-10-08

Nama di atas dipertahankan sebagai nama logis Blueprint. Database hosting authoritative
menggunakan nama fisik berikut, disetujui melalui `ADR-001_EXISTING_MASTER_TABLE_MAPPING.md`:

```text
tbl_propinsi  -> wil_provinsi
tbl_kabkota   -> wil_kabkot
tbl_kecamatan -> wil_kecamatan
tbl_kelurahan -> wil_kelurahan
tbl_bank      -> bank
tbl_cabang    -> bank_cabang
```

Implementasi database menggunakan adapter mapping tersebut. Tabel fisik tidak di-rename,
dibuat ulang, atau dimigrasikan oleh keputusan ini. Nama kolom dan tipe aktual tetap harus
dikonfirmasi melalui PT-003 sebelum pekerjaan database-dependent dilanjutkan.

Nama kolom dan tipe fisik hasil PT-003 bersifat authoritative. Perbedaan dengan nama field
logis pada Blueprint diselesaikan pada repository/adapter aplikasi dan tidak menjadi alasan
untuk mengubah schema database existing tanpa migration approval terpisah.

Implementasi backend harus menyesuaikan dengan struktur aktual database existing.

### 4.2 Koneksi Database

Parameter koneksi database **belum ditanamkan ke source code** pada tahap blueprint.

Backend PHP hanya menyiapkan konfigurasi seperti:

```text
DB_HOST
DB_PORT
DB_NAME
DB_USER
DB_PASSWORD
DB_CHARSET
```

Nilai aktual akan diberikan kemudian.

Contoh struktur konfigurasi:

```php
return [
    'host'     => getenv('DB_HOST'),
    'port'     => getenv('DB_PORT') ?: '3306',
    'database' => getenv('DB_NAME'),
    'username' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'charset'  => getenv('DB_CHARSET') ?: 'utf8mb4',
];
```

Credential production tidak boleh di-hardcode atau di-commit ke repository.

---

## 4A. Hosting Environment Constraint

Deployment backend MyInfo berjalan pada **shared hosting dengan cPanel dan akses Terminal**.

Baseline operasional:

```text
PHP 8.x
MySQL
cPanel
Terminal / PHP CLI
cPanel Cron
HTTPS
```

Arsitektur v1.2 **tidak boleh bergantung** pada service yang harus hidup terus-menerus seperti:

```text
Redis daemon wajib
RabbitMQ wajib
Supervisor wajib
systemd service custom
queue worker permanen
WebSocket daemon permanen
Docker daemon di server production
```

Jika pekerjaan background diperlukan, baseline menggunakan:

```text
PHP CLI script
+
cPanel Cron
+
MySQL state/checkpoint
```

Contoh penggunaan Cron:

```text
sync maintenance
usage aggregation
API quota rollup
cleanup log
expire OTP/session
snapshot generation
scheduled integrity check
```

Pekerjaan batch harus:

```text
idempotent
dapat dilanjutkan
memiliki checkpoint
memiliki batas batch
tidak mengandalkan proses panjang tanpa recovery
```

Terminal cPanel dapat digunakan untuk deployment, migration terkontrol, diagnostic, dan menjalankan PHP CLI.


---

## 5. Database Master Wilayah

### tbl_propinsi

Minimal:

```text
KodePropinsi
NamaPropinsi
```

Contoh:

```text
31 | DKI JAKARTA
36 | BANTEN
```

### tbl_kabkota

Minimal:

```text
KodeKabkota
KodePropinsi
NamaKabkota
Jenis
```

### tbl_kecamatan

Minimal:

```text
KodeKecamatan
KodeKabkota
NamaKecamatan
```

### tbl_kelurahan

Minimal:

```text
KodeKelurahan
KodeKecamatan
NamaKelurahan
KodePos
```

Aturan:

```text
1 kelurahan -> tepat 1 kode pos
1 kode pos  -> dapat digunakan banyak kelurahan
```

Tidak diperlukan tabel kode pos terpisah.

---

## 6. Database Bank

### tbl_bank

Minimal:

```text
KodeBank
NamaBank
NamaSingkat
SwiftCode
Kepemilikan
TypeBank
JenisBank
Status
Website
```

### tbl_cabang

Struktur existing yang digunakan:

```text
KodeCabang
NamaCabang
KodeBank
Type
Alamat

KodePropinsi
KodeKabkota
KodeKecamatan
KodeKelurahan

CodePlus
Latitude
Longitude

Status
```

Jika `Latitude` dan `Longitude` belum ada pada tabel production existing, penambahannya dilakukan melalui migration yang disetujui dan tidak mengubah data existing lain.

Status cabang:

```text
ACTIVE
INACTIVE
```

Cabang tutup tidak dihapus dari master.

---

## 7. Relasi Bank ke Wilayah

Bank tidak memiliki master wilayah sendiri.

```text
tbl_cabang
   |
   +-- KodePropinsi
   +-- KodeKabkota
   +-- KodeKecamatan
   +-- KodeKelurahan
             |
             v
       MASTER WILAYAH
```

Kode Pos diambil dari:

```text
tbl_kelurahan.KodePos
```

Tidak perlu menduplikasi Kode Pos di `tbl_cabang`.

---

## 8. Plus Code, Latitude dan Longitude

### 8.1 Source

Admin dapat copy-paste Plus Code langsung dari Google Maps ke field:

```text
CodePlus
```

### 8.2 Tombol Update Latitude/Longitude

Form cabang pada Admin Dashboard harus memiliki tombol:

```text
[ UPDATE LAT/LNG DARI PLUS CODE ]
```

Flow:

```text
Input / paste CodePlus
        |
        v
Validate format
        |
        v
Resolve Latitude / Longitude
        |
        v
Isi field Latitude dan Longitude
        |
        v
Refresh embedded map preview
        |
        v
Admin cek marker
        |
        v
Save to Draft
```

### 8.3 Strategi Resolve

Prioritas:

**A. Full / Global Plus Code**

Jika nilai `CodePlus` adalah full Plus Code yang valid, backend dapat decode langsung menggunakan algoritma Open Location Code dan mengambil titik tengah area kode.

Keuntungan:

- tidak membutuhkan request Google Geocoding
- cepat
- dapat dilakukan server-side
- cocok untuk bulk processing

**B. Short / Compound Plus Code**

Jika Plus Code yang dipaste berupa short/compound code yang membutuhkan konteks wilayah, backend dapat menggunakan:

- alamat + wilayah sebagai context, atau
- Google Geocoding API

Hasil harus mengembalikan latitude/longitude sebelum disimpan.

### 8.4 Preview Wajib

Latitude/Longitude hasil resolve **tidak langsung dianggap benar**.

Admin harus melihat:

```text
CodePlus
Latitude
Longitude
Embedded Map
Marker
```

sebelum Save/Submit Review.

### 8.5 Tombol Tambahan

Admin Dashboard direkomendasikan memiliki:

```text
[ UPDATE LAT/LNG ]
[ BUKA DI GOOGLE MAPS ]
[ VALIDATE LOCATION ]
```

Pada list cabang dapat disediakan:

```text
[ UPDATE MISSING LAT/LNG ]
```

untuk bulk processing cabang yang:

```text
CodePlus IS NOT NULL
AND
Latitude IS NULL OR Longitude IS NULL
```

Bulk update harus menghasilkan summary:

```text
SUCCESS
INVALID CODE
NEEDS CONTEXT
API ERROR
UNCHANGED
```

Bulk update tidak langsung publish ke production. Hasil masuk workflow Draft -> Review -> Publish.

---

## 9. High Level Architecture

```text
                     INTERNET
                         |
                         v
                +-----------------+
                |   PHP REST API  |
                |     /api/v1     |
                +--------+--------+
                         |
              +----------+-----------+
              v                      v
         +---------+           +--------------+
         |  MySQL  |           | Third Party  |
         +---------+           | Google       |
                               | Wablas       |
                               +--------------+

              ANDROID NATIVE
        +---------------------------+
        | Kotlin                    |
        | ViewModel                 |
        | Repository                |
        | Room                      |
        | Encrypted Local DB        |
        | API Client                |
        | Secure Token Storage      |
        +---------------------------+
```

---

## 10. Backend Stack

```text
PHP 8.x
MySQL
Bootstrap 5
REST API
HTTPS
```

Admin Dashboard:

```text
PHP
Bootstrap 5
Desktop-first
Responsive mobile
```

Area modular:

```text
auth
wilayah
bank
sync
users
admin
publish
audit
settings
app-config
```

---

## 10A. API Surface Separation

MyInfo memiliki dua surface API yang berbeda.

### A. MyInfo App API

Digunakan hanya oleh APK MyInfo.

Contoh namespace:

```text
/api/v1/app/config
/api/v1/app/auth/*
/api/v1/app/profile/*
/api/v1/app/wilayah/*
/api/v1/app/bank/*
/api/v1/app/sync/*
```

Authentication:

```text
MyInfo User
-> Access Token
-> Refresh Token
-> Device Session
```

Tidak menggunakan Commercial API Key, plan, quota berbayar, atau billing.

### B. Commercial Data API

Digunakan oleh client/developer eksternal.

Namespace:

```text
/api/v1/data/*
```

Authentication:

```text
API Client
-> API Key
-> Scope
-> Plan
-> Rate Limit
-> Quota
```

Commercial API **tidak menggunakan akun/login Android**.

Aturan mutlak:

```text
APK USER != API CLIENT
APK ACCESS TOKEN != COMMERCIAL API KEY
APK AUTH != COMMERCIAL API AUTH
APK USAGE != COMMERCIAL API QUOTA
```

Keduanya boleh membaca authoritative master data yang sama, tetapi identity, security, accounting, dan lifecycle credential terpisah.


---

## 11. Android Architecture

Platform:

**Android Native Kotlin**

Arsitektur:

```text
UI
 |
 v
ViewModel
 |
 v
Repository
 +-- Local Data Source -> Room -> Encrypted Local DB
 |
 +-- Remote Data Source -> REST API
```

Modul logis:

```text
app
core
auth
home
wilayah
bank
favorite
history
profile
sync
config
```

---

## 12. Android Local Database

APK membawa database awal:

```text
Wilayah
Bank
Cabang
Latitude
Longitude
Data Version
```

APK harus dapat digunakan langsung setelah install tanpa download database awal.

Local database:

```text
Room
+
Encrypted SQLite-compatible storage
```

Data Wilayah dan Bank tetap dikategorikan sebagai data publik. Encryption digunakan untuk memperkeras akses langsung, bukan menjadikannya rahasia absolut.

Credential/token tidak disimpan di Room.

---

## 13. Navigation

Bottom Navigation:

```text
HOME
WILAYAH
BANK
FAVORIT
PROFIL
```

Modul baru masa depan masuk melalui Home, bukan menambah Bottom Navigation tanpa batas.

---

## 14. Home

Tidak ada global search.

```text
MYINFO

Informasi Indonesia
dalam satu aplikasi

[ DATA WILAYAH ]
[ DATA BANK ]

Modul lainnya...
```

---

## 15. Modul Wilayah

Landing:

```text
WILAYAH

[ Cari Wilayah / Kode ]

atau

[ TELUSURI WILAYAH ]
```

Dua jalur:

```text
SEARCH
atau
BROWSE
```

Search dilakukan real-time terhadap database lokal.

Browse menggunakan layar bertingkat:

```text
Provinsi
 -> Kab/Kota
 -> Kecamatan
 -> Kelurahan
 -> Detail
```

Setiap level memiliki local search.

---

## 16. Detail Wilayah

Semua kode administratif harus tampil.

Contoh:

```text
SENAYAN

Kelurahan
Senayan

Kode Kelurahan
3171021001

Kecamatan
Kebayoran Baru

Kode Kecamatan
317102

Kab/Kota
Jakarta Selatan

Kode Kab/Kota
3171

Provinsi
DKI Jakarta

Kode Provinsi
31

Kode Pos
12190

[COPY]
[SHARE]
[FAVORIT]
```

---

## 17. Modul Bank

Landing:

```text
[ CARI CABANG ]

atau

[ PILIH BANK ]

[ BANK TERDEKAT ]
```

Filter:

```text
Bank
Wilayah
Type
```

Search hanya dalam Modul Bank:

```text
Kode Bank
Nama Bank
Kode Cabang
Nama Cabang
```

Tidak ada cross-module global search.

---

## 18. Detail Cabang

```text
BCA

KCP GADING SERPONG

Kode Bank
014

Kode Cabang
1234

Type
KCP

Alamat
Jl. ...

Kelurahan
...

Kecamatan
...

Kab/Kota
...

Provinsi
...

Kode Pos
...

Plus Code
...

[COPY]
[SHARE]
[FAVORIT]

------------------

GOOGLE MAP
[embedded map]
```

---

## 19. Nearby Bank

Location permission hanya diminta ketika user menggunakan Nearby.

Default radius:

```text
5 km
```

Pilihan:

```text
1 km
2 km
5 km
10 km
25 km
```

UI:

```text
[ Semua Bank ]
[ 5 km ]

EMBEDDED GOOGLE MAP

Cabang di sekitar Anda

BCA KCP ...
850 m

Mandiri ...
1,2 km
```

List diurutkan berdasarkan jarak.

---

## 20. Android Permissions

Runtime permission v1:

```text
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
POST_NOTIFICATIONS
```

Tidak diperlukan:

```text
READ_PHONE_NUMBERS
READ_PHONE_STATE
READ_SMS
READ_CONTACTS
CALL_LOG
ACCESS_BACKGROUND_LOCATION
CAMERA
MICROPHONE
```

Location diminta hanya saat Nearby.

---

## 21. Favorite dan Search History

Favorite disimpan lokal dan terikat UserID lokal.

Favorite dapat menyimpan:

```text
Wilayah
Cabang Bank
```

Search History:

- lokal
- tidak dikirim server
- tidak disinkronisasi
- dapat dihapus per item / clear all

---

## 22. Authentication Mode

Dikontrol Backend:

```text
REQUIRED
OPTIONAL
DISABLED
```

Provider:

```text
Email + Password
Google
WhatsApp OTP
```

Masing-masing provider dapat ON/OFF dari Dashboard:

```text
Email Login          ON/OFF
Google Login         ON/OFF
WhatsApp Login       ON/OFF
```

Tidak membutuhkan update APK.

---

## 23. Google Login

Flow:

```text
Continue with Google
 -> Google authentication
 -> Android menerima credential
 -> Backend PHP verify
 -> Cari / buat MyInfo User
 -> Cek nomor HP
 -> Jika belum verified:
      Input nomor HP
      -> OTP Wablas
      -> Verify
 -> Home
```

Nomor HP wajib untuk akun Google.

---

## 24. WhatsApp OTP

Flow:

```text
Input nomor HP
 -> Backend generate OTP
 -> Wablas
 -> WhatsApp user
 -> Input OTP
 -> Backend verify
```

Tidak membaca nomor SIM, SMS, Contact atau Phone State.

Credential Wablas hanya di server.

---

## 25. User Account

### tbl_users

```text
UserID
Nama
Email
NoHP
EmailVerifiedAt
PhoneVerifiedAt
Status
CreatedAt
UpdatedAt
LastLoginAt
LastActiveAt
```

Status:

```text
ACTIVE
SUSPENDED
DISABLED
```

### tbl_user_auth

```text
ID
UserID
Provider
ProviderUID
PasswordHash
CreatedAt
UpdatedAt
```

Provider:

```text
EMAIL
GOOGLE
PHONE
```

Satu UserID dapat memiliki beberapa provider.

---

## 26. Session dan Device

Menggunakan:

```text
Access Token
Refresh Token
```

Refresh Token baseline:

```text
30 hari
```

Maximum:

```text
3 device / account
```

Server menyimpan:

```text
SessionID
UserID
DeviceID internal
DeviceModel
AndroidVersion
AppVersion
IPAddress
CreatedAt
LastActiveAt
RevokedAt
```

Password change:

```text
Current device -> tetap login
Device lain    -> revoke
```

Admin dan user dapat revoke device sesuai hak akses.

---

## 27. Offline Behavior

Jika user sebelumnya sudah login:

```text
Wilayah              AVAILABLE
Bank                 AVAILABLE
Search               AVAILABLE
Favorite             AVAILABLE
History              AVAILABLE
Nearby distance      AVAILABLE
```

Tidak tersedia ketika server down:

```text
Login baru
Sync
OTP
Google Auth
Online Map Tiles
```

Offline session baseline:

```text
30 hari
```

Database lokal tidak dihapus ketika session expire.

---

## 28. REST API

Base:

```text
/api/v1/
```

Breaking change:

```text
/api/v2/
```

Endpoint baseline:

```text
/api/v1/config

/api/v1/auth/login
/api/v1/auth/google
/api/v1/auth/otp/request
/api/v1/auth/otp/verify
/api/v1/auth/refresh
/api/v1/auth/logout

/api/v1/profile
/api/v1/profile/devices

/api/v1/wilayah/search
/api/v1/wilayah/propinsi
/api/v1/wilayah/kabkota
/api/v1/wilayah/kecamatan
/api/v1/wilayah/kelurahan

/api/v1/banks
/api/v1/banks/{kodebank}
/api/v1/branches
/api/v1/branches/{kode}
/api/v1/branches/nearby

/api/v1/sync/status
/api/v1/sync/changes
/api/v1/sync/snapshot
```

Jika login:

```http
Authorization: Bearer ACCESS_TOKEN
```

---

## 29. Rate Limit

Wajib untuk:

```text
Login
OTP Request
OTP Verify
Password Reset
Sync
```

Basis:

```text
UserID
IP
Endpoint
Phone Number
```

---

## 30. HTTPS

Semua API menggunakan HTTPS.

Android:

```text
cleartextTrafficPermitted = false
```

---

## 31. Remote Config

Contoh:

```json
{
  "application_enabled": true,
  "maintenance": false,
  "auth_mode": "OPTIONAL",
  "auth_email": true,
  "auth_google": true,
  "auth_whatsapp": true,
  "module_wilayah": true,
  "module_bank": true,
  "feature_nearby": true,
  "feature_maps": true
}
```

---

## 32. Module Kill Switch

Dashboard dapat mengontrol:

```text
Wilayah     ON/OFF
Bank        ON/OFF
Nearby      ON/OFF
Maps        ON/OFF
```

Tanpa rebuild APK.

Maintenance Mode juga ON/OFF dari Dashboard.

---

## 33. Data Version dan Sync

Version per modul:

```text
Wilayah Version
Bank Version
```

Normal update:

```text
INCREMENTAL
```

Jika terlalu jauh tertinggal:

```text
FULL SNAPSHOT
```

Server menentukan update strategy.

### tbl_sync_changes

```text
SyncID
Module
TableName
RecordKey
Action
DataVersion
CreatedAt
```

Action:

```text
INSERT
UPDATE
DELETE
```

Android menyimpan `last_sync_id`.

Delete dikirim sebagai tombstone.

---

## 34. Silent Update

Data sync dilakukan diam-diam jika aman.

Home tidak ditahan oleh sync normal.

Force Update hanya digunakan ketika versi APK berada di bawah `minimum_version`.

Server menyimpan:

```text
latest_version
minimum_version
force_update
store_url
```

---

## 35. Distribution

Flow:

```text
Website MyInfo
 -> Get App / Download
 -> Google Play Store
```

Direct APK dapat ditambahkan kemudian jika diperlukan.

Package ID dan signing key harus konsisten.

---

## 36. Admin Roles

Role minimal:

```text
SUPERADMIN
USER / EDITOR
```

SUPERADMIN:

```text
Database
Wilayah
Bank
Import
Review
Publish
Rollback
Audit semua user
Android Users
App Config
Settings
API Keys
Wablas
Google Config
Version Control
```

EDITOR:

```text
Database
Wilayah
Bank
Insert
Update
Delete
CSV Import
Create Draft
Submit Review
```

EDITOR tidak dapat:

```text
Settings
API Keys
Wablas Key
Google Key
Security Config
```

Menu Settings tidak dirender sama sekali untuk Editor.

Backend tetap harus mengembalikan `403 Forbidden` bila URL dipanggil langsung.

---

## 37. Admin Session

Login:

```text
Email
Password
```

Tidak menggunakan OTP Admin pada v1.

Session:

```text
Idle timeout       30 menit
Absolute session   8-12 jam
```

Aksi sensitif dapat meminta password ulang:

```text
Publish
Rollback
API key changes
Wablas config
Google config
Security config
```

---

## 38. Admin Dashboard

Menampilkan:

```text
Jumlah Provinsi
Jumlah Kab/Kota
Jumlah Kecamatan
Jumlah Kelurahan

Jumlah Bank
Jumlah Cabang

Draft
Waiting Review
Last Publish

Total Android User
Active Today
Active 7 Days
Active 30 Days
```

Android user table:

```text
Nama
Email
NoHP
Provider
Last IP
Last Login
Last Active
Device
Android Version
App Version
Data Version
Status
```

---

## 39. Draft -> Review -> Publish

Production tidak berubah langsung saat Editor mengedit.

```text
EDIT
 -> DRAFT
 -> SUBMIT REVIEW
 -> REVIEW
      -> REJECT
      -> APPROVE
           -> PUBLISH
                -> PRODUCTION
                -> SYNC LOG
                -> ANDROID
```

---

## 40. Change Request

### tbl_change_request

```text
ChangeID
Module
TableName
RecordKey
Action
OldData JSON
NewData JSON
Status
CreatedBy
ReviewedBy
CreatedAt
ReviewedAt
PublishedAt
```

Status:

```text
DRAFT
WAITING_REVIEW
APPROVED
REJECTED
PUBLISHED
CANCELLED
```

Tidak membuat tabel draft duplikat untuk setiap master.

---

## 41. CSV Import

Flow:

```text
UPLOAD
 -> PARSE
 -> VALIDATE
 -> COMPARE PRODUCTION
 -> PREVIEW
 -> COMMIT TO DRAFT
 -> REVIEW
 -> PUBLISH
```

Preview:

```text
NEW
UPDATE
UNCHANGED
ERROR
DUPLICATE
```

Parent validation wajib:

```text
Kab/Kota    -> Provinsi valid
Kecamatan   -> Kab/Kota valid
Kelurahan   -> Kecamatan valid
Cabang      -> seluruh kode wilayah valid
```

---

## 42. Audit Log

### tbl_audit_log

```text
ID
AdminID
AdminName
TableName
RecordKey
Action
OldData JSON
NewData JSON
IPAddress
UserAgent
CreatedAt
```

INSERT:

```text
OldData = null
NewData = record
```

UPDATE:

```text
OldData = before
NewData = after
```

DELETE:

```text
OldData = record
NewData = null
```

Editor hanya melihat aktivitas sendiri.

Superadmin melihat seluruh audit.

---

## 43. Release dan Rollback

Version tidak pernah mundur.

Contoh:

```text
Bank v28
Bank v29  <- bermasalah
Rollback
Bank v30  <- isi dikembalikan ke state yang dipilih
```

Android menerima:

```text
29 -> 30
```

bukan:

```text
29 -> 28
```

---

## 44. Settings

Superadmin only.

Kategori:

```text
Authentication
WhatsApp / Wablas
Google
Maps
Application
Sync
Version
Security
```

Secret tidak pernah dikirim ke Android.

---

## 44A. Commercial Data API

Commercial Data API adalah produk backend terpisah dari APK.

### 44A.1 Admin Menu

Dashboard Superadmin memiliki area:

```text
API COMMERCIAL
├── Clients
├── API Keys
├── Plans
├── Scopes
├── Usage
├── Request Logs
└── Billing Foundation
```

### 44A.2 Tabel Sistem

Minimal:

```text
tbl_api_clients
tbl_api_keys
tbl_api_plans
tbl_api_usage
tbl_api_usage_daily
tbl_api_request_logs
```

Boleh disesuaikan setelah migration review, tetapi tidak boleh dicampur dengan:

```text
tbl_users
tbl_user_auth
tbl_user_sessions
```

### 44A.3 API Key

Contoh format:

```text
mi_live_xxxxxxxxxxxxxxxxx
mi_test_xxxxxxxxxxxxxxxxx
```

Key hanya ditampilkan penuh saat dibuat.

Database menyimpan:

```text
KeyID
ClientID
KeyPrefix
KeyHash
Scopes
PlanID
Status
ExpiresAt
CreatedAt
LastUsedAt
```

Raw API Key tidak disimpan plaintext.

Request:

```http
X-API-Key: mi_live_xxxxxxxxxxxxxxxxx
```

### 44A.4 Scope

Read scope:

```text
wilayah.read
bank.read
branch.read
```

Submission scope:

```text
wilayah.submit
bank.submit
branch.submit
```

Gunakan istilah `submit`, bukan direct production write.

### 44A.5 Read API

Contoh:

```text
GET /api/v1/data/wilayah/provinsi
GET /api/v1/data/wilayah/kabkota
GET /api/v1/data/wilayah/kecamatan
GET /api/v1/data/wilayah/kelurahan
GET /api/v1/data/wilayah/search
GET /api/v1/data/banks
GET /api/v1/data/branches
```

### 44A.6 Submit API

Client yang memiliki scope submit dapat mengirim proposal perubahan:

```text
POST /api/v1/data/wilayah/submit
POST /api/v1/data/bank/submit
POST /api/v1/data/branch/submit
```

Flow wajib:

```text
API CLIENT
-> VALIDATE
-> CHANGE REQUEST / DRAFT
-> REVIEW
-> PUBLISH
```

Commercial API tidak pernah diberi endpoint yang langsung mengubah production master tanpa workflow approval.

### 44A.7 Plans, Rate Limit, Quota

Contoh:

```text
FREE
BASIC
PRO
ENTERPRISE
```

Plan dapat menentukan:

```text
allowed scopes
requests per minute/hour
monthly quota
expiry
status
```

Implementasi pada shared hosting menggunakan PHP + MySQL.

Redis tidak menjadi dependency wajib.

### 44A.8 Usage

Dashboard dapat menampilkan:

```text
Client
Plan
Requests Today
Requests This Month
Quota
Last Request
Top Endpoint
2xx / 4xx / 5xx
429 Count
```

Raw request logs dapat memiliki retention period agar tabel tidak membesar tanpa batas.

cPanel Cron dapat digunakan untuk:

```text
daily aggregation
monthly usage rollup
log cleanup
key expiry maintenance
```

### 44A.9 Billing Foundation

v1.2 menyediakan foundation status billing/plan, bukan wajib payment gateway otomatis.

Contoh:

```text
ACTIVE
TRIAL
PAST_DUE
SUSPENDED
CANCELLED
```

Aktivasi plan dapat dikelola Superadmin sampai payment integration ditambahkan sebagai task terpisah.


---

## 45. Security Rules

Tidak boleh commit:

```text
Wablas Secret
Production DB Password
Google Private Credential
Signing Password
Server Secret
JWT Secret
```

Environment minimal:

```text
Development
Staging
Production
```

Android production tidak boleh menunjuk ke Development API.

---

## 46. Theme

```text
LIGHT
DARK
SYSTEM
```

Default:

```text
SYSTEM
```

Arah UI:

```text
Material-style native Android
Clean
Minimal
Readable
Cards ringan
Spacing lega
Accent terbatas
```

---

## 47. UI State Persistence

Saat Back:

```text
Search Query
Filter
Scroll Position
Selected Province
Selected District
Selected Bank
Selected Type
```

harus tetap selama navigation session.

---

## 48. Error Handling

Harus membedakan:

```text
No Internet
Server Error
Authentication Error
Permission Denied
Data Sync Error
Database Error
Maps Error
Maintenance
Force Update
```

Tidak menggunakan satu pesan generik untuk semua kegagalan.

---

## 49. Privacy

Kumpulkan hanya data yang diperlukan.

Tidak mengakses:

```text
Contacts
SMS
Call Log
Phone State
Background Location
```

Search History tetap lokal pada v1.

Profile:

```text
Data Saya
Perangkat Saya
Logout
Delete Account
Privacy Policy
Terms
```

---

## 50. Performance Principle

Search Wilayah dan Bank harus local-first.

Jika data sudah ada di encrypted local DB, pencarian tidak boleh bergantung pada network.

Target:

```text
Open module cepat
Search realtime
Browse hierarchy tanpa network loading
Detail lokal tampil segera
Map load terpisah
```

---

## 51. Architectural Rules

Aturan ini tidak boleh dilanggar tanpa keputusan arsitektur baru:

```text
Android tidak konek langsung ke MySQL.

Database existing di hosting adalah authoritative source.

Backend PHP menerima parameter koneksi kemudian; credential tidak di-hardcode.

Bank dan Wilayah adalah modul terpisah.

Tidak ada global cross-module search.

Bank menggunakan master Wilayah.

Kode wilayah menggunakan VARCHAR.

Kode Pos berada pada tbl_kelurahan.

CodePlus disimpan pada tbl_cabang.

Latitude/Longitude dapat dihasilkan dari CodePlus melalui Admin Dashboard.

Update Lat/Lng harus memiliki preview map sebelum Publish.

Database Android tersedia offline dan encrypted.

Production tidak berubah langsung dari Editor.

Draft harus melewati Review -> Publish.

Audit Log berbeda dari Sync Log.

Release version tidak boleh mundur.

Rollback menghasilkan version baru.

Secret Wablas tidak berada di Android.

Settings hanya Superadmin.

Permission diminta saat diperlukan.

Login mode dikontrol server.

Feature/module dapat dikontrol server.

Modul baru tidak boleh memaksa redesign fondasi.

Shared hosting adalah baseline deployment production.

Backend tidak boleh mengharuskan daemon/worker permanen.

Cron/background baseline memakai PHP CLI + cPanel Cron + MySQL checkpoint.

Commercial API dipisahkan dari App API.

APK User tidak sama dengan API Client.

Access Token APK tidak sama dengan Commercial API Key.

Commercial API quota/billing tidak berlaku ke APK.

Raw Commercial API Key tidak disimpan plaintext.

Commercial API submit tidak boleh direct-write production.

Commercial API submit wajib masuk Draft -> Review -> Publish.
```

---

## 52. Development Phases

### PHASE 1 — FOUNDATION

```text
Project bootstrap
Environment
Read existing database schema
Database connection abstraction
System tables
REST API foundation
Admin authentication
Android project shell
Remote config
```

### PHASE 2 — AUTHENTICATION

```text
Email
Google
WhatsApp OTP
Access/Refresh Token
Device Session
Account Linking
```

### PHASE 3 — WILAYAH

```text
Existing DB adapter
API
Encrypted Room snapshot
Browse
Search
Detail
Favorite
```

### PHASE 4 — BANK

```text
Existing DB adapter
Bank API
Cabang API
Encrypted Room snapshot
Search
Filter
Detail
Plus Code
Latitude/Longitude updater
Embedded Map
```

### PHASE 5 — NEARBY

```text
Location Permission
Latitude/Longitude
Distance Calculation
Map
List
Radius
Bank Filter
```

### PHASE 6 — SYNC

```text
Module Version
Incremental Sync
Tombstone
Snapshot
Silent Update
Recovery
```

### PHASE 7 — ADMIN

```text
Dashboard
Wilayah CRUD
Bank CRUD
CSV Import
Validation
Plus Code -> Lat/Lng Update
Map Validation
Change Request
Review
Publish
```

### PHASE 8 — RELEASE MANAGEMENT

```text
Module Release
Rollback
Audit
App Version
Force Update
Kill Switch
```

### PHASE 9 — SECURITY

```text
HTTPS
Rate Limiting
Token Security
Permission Audit
Secret Handling
Session Management
```

### PHASE 10 — COMMERCIAL DATA API

```text
API Client Management
API Key Generator
Plans & Scopes
Rate Limit & Quota
Wilayah Read API
Bank Read API
Partner Submit API
Usage Dashboard
Billing Foundation
Shared-hosting Cron aggregation
Commercial API Security Review
```

### PHASE 11 — QA & RELEASE

```text
Unit Test
API Test
Android Test
Commercial API Test
Offline Test
Sync Test
Upgrade Test
Rollback Test
Permission Test
Play Store Release
```

---

## 53. Definition of Done MyInfo v1

MyInfo v1 selesai jika:

```text
Android Native stabil.

Email Login bekerja.
Google Login bekerja.
WhatsApp OTP bekerja.

Auth REQUIRED bekerja.
Auth OPTIONAL bekerja.
Auth DISABLED bekerja.

Wilayah dapat digunakan offline.
Browse Wilayah bekerja.
Realtime Search bekerja.
Detail seluruh kode tampil.

Bank dapat digunakan offline.
Bank Search bekerja.
Filter bekerja.
Cabang tampil lengkap.

CodePlus dapat diinput dari Dashboard.
Latitude/Longitude dapat di-update dari CodePlus.
Map preview memvalidasi lokasi sebelum Publish.

Embedded Map Android bekerja.
Nearby bekerja.
Distance sorting bekerja.

Favorite lokal bekerja.
History lokal bekerja.

Encrypted local DB aktif.

Incremental Sync bekerja.
Full Snapshot bekerja.
Silent Sync bekerja.

Version Wilayah independen.
Version Bank independen.

Admin Dashboard berjalan.
CSV validation berjalan.
Draft/Review/Publish berjalan.
Audit berjalan.
Rollback berjalan.

Settings hanya Superadmin.
Module Kill Switch bekerja.

App Version Check bekerja.
Minimum Version bekerja.

Offline Mode bekerja.

HTTPS only.
Rate limit aktif.
Session/device management aktif.

Commercial API terpisah dari App API.
API Client dan API Key Management bekerja.
API Key disimpan hashed.
Plan/Scope/Quota/Rate Limit bekerja.
Commercial Wilayah Read API bekerja.
Commercial Bank Read API bekerja.
Submit API masuk Draft/Review/Publish.
Usage Dashboard bekerja.
Shared-hosting Cron jobs dapat dijalankan melalui cPanel.

Google Play release siap.
```

---

## 54. Source of Truth

Dokumen ini menjadi baseline arsitektur MyInfo v1.

Jika implementasi berbeda:

```text
BLUEPRINT MENANG
```

kecuali perubahan:

1. disepakati,
2. dicatat,
3. memperbarui blueprint,
4. baru diimplementasikan.

Claude Code maupun agent lain tidak diperbolehkan mengubah desain fundamental tanpa keputusan arsitektur eksplisit.

---

**END OF BLUEPRINT — MYINFO v1.2**
