Lewati ke isi

REFACTOR_PLAN.md

Garuda Chain — Rencana Refactor Bertahap

Metadata
Versi dokumen 1.0.0
Prinsip utama Tidak mengganggu production
Pendekatan Parallel implementation + gradual migration
Terakhir diperbarui 2026-07-04

1. Prinsip Refactor

┌────────────────────────────────────────────────────────────┐
│  ATURAN MUTLAK                                              │
├────────────────────────────────────────────────────────────┤
│  1. JANGAN hapus fitur yang berjalan di production          │
│  2. JANGAN ubah UI/UX yang dipakai pengguna tanpa approval  │
│  3. JANGAN deploy refactor besar langsung ke mainnet        │
│  4. SETIAP perubahan harus backward compatible              │
│  5. SETIAP fase punya rollback plan                         │
│  6. SETIAP fase punya test suite                            │
│  7. Production tetap di apps/api, apps/wallet (v1)          │
│  8. Eksperimen di staging: apps/api-v2, branch develop      │
└────────────────────────────────────────────────────────────┘

2. Diagram Strategi

Production (v1)                    Staging (v2 / refactor)
─────────────────                  ─────────────────────────
apps/api          ─── parallel ──▶ apps/api-v2
apps/wallet       ─── gradual ──▶ apps/wallet (module shell)
packages/sdk      ─── extend ───▶ packages/{sdk,types,ui-core,config}
chain/deployments ◀── SSOT ────── generate-deployments.ts
data/*.json       ─── migrate ──▶ PostgreSQL (staging first)

3. Fase Refactor

Fase 0 — Dokumentasi & Inventaris ✅

Durasi: 1 minggu · Risk: None · Production impact: None

Task Status Output
SYSTEM_ARCHITECTURE.md docs/architecture/
PROJECT_ROADMAP.md docs/architecture/
API_DOCUMENTATION.md docs/architecture/
DATABASE_SCHEMA.md docs/architecture/
SECURITY_AUDIT.md docs/architecture/
REFACTOR_PLAN.md Dokumen ini
Update mkdocs nav mkdocs.yml

Rollback: N/A (docs only)


Fase 1 — Shared Foundation

Durasi: 2–3 minggu · Risk: Low · Production impact: None (build-time only)

1.1 Deployment Registry Generator

Masalah: packages/sdk/src/deployments.ts drift dari chain/deployments/mainnet.json

Solusi:

chain/deployments/*.json
        ↓ scripts/generate-deployments.ts (prebuild)
packages/sdk/src/deployments.ts (generated)

Files baru: - scripts/generate-deployments.ts - packages/config/ — Zod schema untuk deployment JSON

Files tidak diubah: Production runtime behavior

Test: Diff generator output vs manual verify addresses

Rollback: Revert script; restore manual deployments.ts


1.2 packages/types

Masalah: Duplikasi type definitions (bridge, GNFT, GarudaPay) di wallet, explorer, api

Solusi:

packages/types/
├── src/
│   ├── gnft.ts
│   ├── bridge.ts
│   ├── garudaPay.ts
│   ├── community.ts
│   └── index.ts
└── package.json

Migrasi konsumen (non-breaking): 1. API imports dari @garuda-chain/types (re-export existing types) 2. Wallet + Explorer: import bertahap per modul 3. Hapus duplikat hanya setelah semua konsumen migrated

Rollback: Revert imports ke local types


1.3 packages/ui-core

Masalah: gnftDisplay.ts duplikat di wallet dan explorer

Solusi:

packages/ui-core/
├── src/
│   ├── gnftDisplay.ts      # unified dengan options
│   ├── formatAddress.ts    # shortenHash / formatShortAddress
│   └── index.ts

Catatan: Explorer hideHolder: true default; Wallet hideHolder: false — satu fungsi, parameter berbeda.

Rollback: Restore local copies


1.4 API Test Bootstrap

Masalah: Zero automated tests di API

Solusi:

apps/api/
├── vitest.config.ts
└── src/__tests__/
    ├── health.test.ts
    ├── walletAuth.test.ts
    ├── communityCheckIn.test.ts
    ├── gnftMetadata.test.ts
    └── bridgeQuote.test.ts

CI: Add npm run test -w @garuda-chain/api to pipeline

Rollback: Remove test files (no production impact)


Fase 2 — API Decomposition (Staging Parallel)

Durasi: 4–6 minggu · Risk: Medium · Production impact: None

2.1 Extract inline routes dari index.ts

Saat ini: ~340 baris bootstrap + inline routes di apps/api/src/index.ts

Target structure (v1 — same app, better organization):

apps/api/src/
├── index.ts              # Bootstrap only (~50 lines)
├── routes/
│   ├── chain.ts          # NEW: blocks, txs, accounts (from index.ts)
│   └── ... (existing)
└── services/
    ├── chainService.ts   # RPC logic extracted
    └── accountService.ts

Approach: Extract tanpa mengubah response shape · Test parity

Rollback: Git revert single PR


2.2 apps/api-v2 Skeleton (Staging Only)

Struktur Clean Architecture:

apps/api-v2/
├── src/
│   ├── domain/
│   │   ├── entities/
│   │   └── repositories/     # interfaces
│   ├── application/
│   │   └── use-cases/
│   ├── infrastructure/
│   │   ├── persistence/
│   │   │   ├── json/           # adapter existing stores
│   │   │   └── postgres/       # new adapter
│   │   └── blockchain/
│   │       └── rpcAdapter.ts
│   └── presentation/
│       ├── routes/
│       └── middleware/
├── package.json
└── Dockerfile

Scope fase 2.2: Read-only endpoints only - GET /health - GET /api/v2/chain - GET /api/v2/network/contracts - GET /api/v2/gnft/listings

Deploy: Staging only, port 4001, Caddy route api-v2.staging.garudachain.id

Rollback: Remove container; v1 unaffected


2.3 Garuda Pay Route Split

Masalah: garudaPay.ts ~700 baris

Target:

apps/api/src/routes/garudaPay/
├── index.ts          # router mount
├── profile.ts
├── charge.ts
├── transfer.ts
├── fiat.ts
└── cs.ts

Constraint: Same URL paths, same response — internal refactor only


Fase 3 — Database Migration (Staging)

Durasi: 4–6 minggu · Risk: High · Production impact: None until Fase 5

3.1 PostgreSQL Setup

# docker-compose.staging.yml addition
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: garuda_staging
    volumes:
      - pgdata:/var/lib/postgresql/data

3.2 Repository Pattern

// domain/repositories/GarudaPayRepository.ts
interface GarudaPayRepository {
  getProfile(address: string): Promise<GarudaPayProfile>;
  saveProfile(address: string, profile: GarudaPayProfile): Promise<void>;
  // ...
}

// infrastructure/persistence/json/JsonGarudaPayRepository.ts  — wraps existing
// infrastructure/persistence/postgres/PgGarudaPayRepository.ts — new

3.3 Dual-Write Migration

Week 1-2: Write to JSON only (baseline)
Week 3-4: Write to JSON + PostgreSQL (dual-write)
Week 5-6: Read from PostgreSQL, verify parity with JSON
Week 7+:  Write PostgreSQL only, JSON as export backup

Verification script: scripts/migrate/verify-garuda-pay-parity.ts

Rollback: Flip env GARUDA_PAY_REPOSITORY=json


Fase 4 — Wallet Modularization

Durasi: 4–6 minggu · Risk: Medium · Production impact: Low (lazy load only)

4.1 Code Splitting

// MainWalletApp.tsx
const MarketScreen = lazy(() => import("./screens/MarketScreen"));
const NFTGalleryScreen = lazy(() => import("./screens/TemplateScreens").then(m => ({ default: m.NFTGalleryScreen })));

Target: Initial bundle < 600KB

4.2 Module Registry (POC)

// lib/modules/registry.ts
export interface GarudaModule {
  id: string;
  tabId?: string;
  load: () => Promise<React.ComponentType>;
}

export const modules: GarudaModule[] = [
  { id: "core", load: () => import("../screens/DashboardScreens") },
  { id: "cards", tabId: "cards", load: () => import("../screens/TemplateScreens") },
  // ...
];

Constraint: Tab behavior identical; only loading mechanism changes

4.3 Wallet Key Security (POC Staging)

Current: sessionStorage plaintext private key

Target:

Unlock → derive sessionToken (random UUID)
       → privateKey in closure/module singleton only
       → sessionStorage stores { sessionToken, address } only
       → clear on lock/tab close

Test: E2E unlock → send → lock → verify key not in sessionStorage

Rollback: Feature flag VITE_SECURE_SESSION=false


Fase 5 — Security Hardening

Durasi: 2–3 minggu · Risk: Low-Medium · Staging first

Change File Rollback
Bridge relay auth routes/bridge.ts Env BRIDGE_RELAY_OPEN=true (dev only)
CORS restrict index.ts Env CORS_ORIGIN=* override
GraphQL auth graphql/ Env GRAPHQL_PUBLIC=true
CSP headers apps/wallet/public/_headers Remove header
Zod validation per route Disable middleware

Production deploy: Only after 14-day staging soak


Fase 6 — Production Migration

Durasi: 4–8 minggu · Risk: High · Requires: All gates passed

Migration Order (safest first)

Order Component Strategy Downtime
1 Deployment registry Build-time Zero
2 Shared packages Deprecation period Zero
3 API inline route extract Blue-green Zero
4 Security hardening Config deploy Zero
5 Wallet code splitting Cloudflare deploy Zero
6 PostgreSQL Garuda Pay Dual-write cutover < 1 min
7 PostgreSQL KYC Dual-write cutover < 1 min
8 Community state DB Background migration Zero
9 API v2 shadow traffic Gradual 10→50→100% Zero
10 Wallet secure session Feature flag rollout Zero

Gate Checklist (per component)

  • [ ] Staging soak ≥ 14 days
  • [ ] Automated tests pass
  • [ ] Smoke test production-like load
  • [ ] Rollback tested
  • [ ] Monitoring alerts configured
  • [ ] Runbook documented
  • [ ] Team sign-off

4. Yang TIDAK Di-refactor

Area Alasan
Smart contracts production Butuh audit + governance; redeploy only
Besu validator setup Operational stability
Wallet visual design / branding User-facing stability
Bottom nav structure UX familiarity
Chain ID 8846 genesis Immutable
Existing API URL paths Backward compatibility

5. Duplikasi Kode — Prioritas Konsolidasi

Duplikat Lokasi Target Fase
gnftDisplay.ts wallet, explorer packages/ui-core 1
formatAddress wallet, explorer packages/ui-core 1
Bridge types wallet, explorer, admin packages/types 1
RPC probing wallet rpc.ts, explorer chain.ts, admin monitor.ts packages/sdk rpcHealth 2
MaterialIcon.tsx wallet, admin packages/ui-core 2
Chain client logic wallet chain.ts, explorer chain.ts SDK + thin adapters 3

Tidak dikonsolidasi: Explorer server cache (Next.js specific), Wallet encrypted storage (client specific)


6. Branch & Release Strategy

main          ← production releases only
develop       ← integration branch
feature/*     ← per-phase work
release/*     ← staging candidates
hotfix/*      ← production critical fixes

Release cadence: - Staging: weekly (auto dari develop) - Production: monthly atau per-milestone (manual gate)


7. Testing Strategy

Level Tool Coverage target
Unit Vitest API services, packages
Integration Vitest + supertest API routes
Contract Foundry Smart contracts (existing)
E2E Wallet Playwright Critical flows (staging)
E2E Staging npm run staging:smoke Deploy gate
Load k6 API read 1000 RPS
Security OWASP ZAP (staging) Quarterly

8. Monitoring Refactor Health

Metric Alert threshold
API error rate > 1% for 5 min
API p99 latency > 2s
Wallet JS errors (Sentry) > 10/min
Bridge relay failures > 3 consecutive
PostgreSQL replication lag > 5s
JSON/DB parity drift Any mismatch

9. Rollback Playbook (Ringkas)

API deploy rollback

# VPS: restore previous Docker image
docker compose -f docker-compose.mainnet.yml -f docker-compose.production.yml up -d --no-deps api

Wallet rollback

# Cloudflare Pages: rollback to previous deployment via dashboard
# Or redeploy previous dist from git tag
git checkout <tag> && npm run wallet:deploy:cloudflare

Database rollback

# Flip repository adapter
export GARUDA_PAY_REPOSITORY=json
# Restore JSON from backup
cp data/garuda-pay-store.json.bak data/garuda-pay-store.json
docker compose restart api

10. Timeline Ringkas

Fase Durasi Production touch?
0 — Dokumentasi 1 minggu
1 — Shared Foundation 2-3 minggu ❌ (build only)
2 — API Decomposition 4-6 minggu
3 — Database Migration 4-6 minggu ❌ (staging)
4 — Wallet Modular 4-6 minggu ❌ (staging) / 🟡 (code split only)
5 — Security Hardening 2-3 minggu 🟡 (after staging soak)
6 — Production Migration 4-8 minggu ✅ (gradual)

Total estimasi: 6–9 bulan untuk refactor penuh dengan zero-downtime migration.


11. Referensi