# Patch `server.js` — biar accounts.db nggak kosong lagi

Migrasi sekali jalan membereskan 403 **sekarang**. Patch ini yang bikin
masalahnya nggak balik lagi tiap ada akun baru / ganti role / verifikasi Discord.

---

## 1. Tambah require (dekat baris 24–28)

```js
const piracyGuard   = require('./piracyGuard');
const subscriptionClient = require('./subscriptionClient');
const voucherClient = require('./voucherClient');
const { syncAccountToStore, migrateAllFromFirestore } = require('./accountsSync'); // ⬅ BARU
```

---

## 2. Sync otomatis tiap tulis ke `accounts`

`syncPublicProfile()` sudah dipanggil di setiap titik yang menulis field publik
akun. Nebeng di situ = satu perubahan, semua call-site kebawa.

Cari `function syncPublicProfile(username, data) {` (± baris 2916) dan ubah jadi:

```js
function syncPublicProfile(username, data) {
  // ⬇ BARU: cerminkan role & field storage ke SQLite (accounts.db), karena
  // piracyGuard/subscriptionClient/voucherClient sekarang baca dari sana,
  // bukan dari Firestore lagi. Sengaja sinkron (better-sqlite3 memang sync)
  // dan di-try/catch supaya kegagalan SQLite nggak menggagalkan register.
  try {
    syncAccountToStore(username, data);
  } catch (e) {
    console.error('[accountsSync] Gagal sync ke SQLite:', e.message);
  }

  const publicRef = db.collection('artifacts').doc(FIREBASE_APP_ID)
    .collection('public').doc('data')
    .collection('public_profiles').doc(username);
  return publicRef.set({ /* ... biarkan apa adanya ... */ }, { merge: true });
}
```

⚠️ **Titik yang TIDAK lewat `syncPublicProfile`** — tambahkan
`syncAccountToStore(username, {...})` manual setelah `accRef.set(...)`:

- endpoint verifikasi Discord (± baris 2301, 2323, 2354) — yang mengubah
  `discordVerified`, `discordRoleTier`, `storageLimit`, `preDiscordStorageLimit`
- titik manapun yang mengubah `role` akun tanpa memanggil `syncPublicProfile`

Contoh:

```js
await accRef.set(update, { merge: true });
syncAccountToStore(username, update);   // ⬅ BARU
```

---

## 3. Endpoint migrasi (biar nggak perlu SSH tiap redeploy)

Taruh persis di bawah endpoint `/api/admin/migrate-public-profiles` (± baris 946).
Sengaja pakai `verifyRequesterRole` (baca **Firestore**), **bukan**
`piracyGuard.requireAdmin` (baca SQLite) — kalau pakai yang SQLite, endpoint
buat memperbaiki SQLite kosong akan ikut 403. Ayam-telur.

```js
// POST /api/admin/migrate-accounts-sqlite — body: { requesterUsername }
// Isi ulang accounts.db (SQLite) dari Firestore. Idempoten, aman diulang.
app.post('/api/admin/migrate-accounts-sqlite', async (req, res) => {
    if (!db) return res.status(503).json({ success: false, error: 'Firestore belum siap di server.' });
    const { requesterUsername } = req.body || {};
    const requesterRole = await verifyRequesterRole(requesterUsername, ['admin', 'admin_utama']);
    if (!requesterRole) {
        return res.status(403).json({ success: false, error: 'Kamu tidak punya izin buat migrasi ini.' });
    }
    try {
        const result = await migrateAllFromFirestore(db, FIREBASE_APP_ID);
        console.log(`[accountsSync] ${result.synced}/${result.total} akun disalin ke SQLite.`);
        res.json({ success: true, ...result });
    } catch (err) {
        console.error('[POST /api/admin/migrate-accounts-sqlite]', err.message);
        res.status(500).json({ success: false, error: err.message });
    }
});
```

---

## 4. Auto-seed saat boot (rekomendasi untuk Railway)

Filesystem Railway tidak persisten — tanpa volume, `accounts.db` hilang tiap
redeploy dan 403-nya balik. Dua pilihan:

**Pilihan A (paling aman):** pasang volume, set env
`ACCOUNTS_DB_PATH=/data/accounts.db` dan `SUBSCRIPTION_DB_PATH` ke volume yang
sama. Tanpa ini, data paket & order langganan juga ikut hilang tiap deploy.

**Pilihan B (tambahan, bukan pengganti):** seed otomatis saat start. Taruh di
dekat blok `errorMonitor.init(...)` (± baris 415):

```js
if (db) {
  migrateAllFromFirestore(db, FIREBASE_APP_ID)
    .then(r => console.log(`✅ accountsSync: ${r.synced}/${r.total} akun siap di SQLite.`))
    .catch(e => console.error('⚠️  accountsSync gagal saat boot:', e.message));
}
```

Kalau akunmu sedikit (ratusan), biaya baca Firestore-nya sekali per boot —
masih murah. Kalau sudah ribuan, pakai Pilihan A saja.
