# Codex Handoff - QRIS Soundbox Platform

Tanggal update: 2026-05-29, Asia/Jakarta.

Dokumen ini adalah snapshot kerja terakhir untuk melanjutkan project tanpa perlu membaca ulang seluruh chat.

## Status Terakhir

- Estimasi MVP / early pilot: 92-94%.
- Estimasi production-ready penuh: 82-85%.
- Platform sudah bukan prototype docs-only. Backend, UI operasional, migration, smoke test, rate limiting, audit logging, async export, runbook, dan script deployment sudah tersedia.
- Fokus terakhir yang selesai: rate limiting + security polish, login audit, admin audit UI real-data, placeholder nav cleanup, dan runbook/checklist produksi.
- Worktree kemungkinan masih dirty karena banyak perubahan aktif. Jangan revert perubahan yang tidak eksplisit diminta.

## Verifikasi Terakhir

- `npm run typecheck`: pass.
- `npm run db:migrate`: pass dan idempotent sampai migration `003_export_job_storage.sql`.
- `npm audit --json`: pass, 0 vulnerability.
- `npm run ui:qa`: pass setelah cleanup placeholder navigation.
- `npm run smoke:e2e`: pass setelah rate limiting dan login audit.
- Quick rate limit test: pass. Login admin salah pertama menghasilkan `401` dengan `RateLimit-Remaining: 0`, request berikutnya menghasilkan `429 RATE_LIMITED`.
- Quick login audit test: pass. Event `admin.login.success`, `admin.login.failed`, `merchant.login.success`, dan `merchant.login.failed` tercatat.
- Quick audit UI API test: pass. `GET /admin/audit-logs?action_contains=.login.&limit=10` mengembalikan event login.
- Production-like env check dummy: pass via `npm run deploy:check-env`, hanya warning opsional untuk `MQTT_SUBSCRIBE`.
- Staging/load/MQTT real sebelumnya sudah pernah diverifikasi: load level 2 1610 requests 0 errors, MQTT broker `mqtts://mqtt.iptek.co:8883` publish/subscribe OK.

## Implementasi Selesai

### 1. Auth, RBAC, dan Security

- Admin session login tersedia lewat `/admin/login`, `/admin/logout`, `/admin/me`.
- Merchant session login tersedia lewat `/merchant/login`, `/merchant/logout`, `/merchant/me`.
- Legacy dev auth bisa dimatikan via env dan production check memblokir konfigurasi yang tidak aman.
- Admin dan merchant bootstrap script tersedia:
  - `scripts/create-admin-user.mjs`
  - `scripts/create-merchant-user.mjs`
- Password policy bootstrap diperketat:
  - minimal 14 karakter;
  - wajib lowercase, uppercase, angka, dan simbol;
  - menolak kata mudah ditebak seperti product/default/password/admin/merchant/qris/soundbox.
- Rate limiting middleware baru:
  - [src/shared/middleware/rateLimit.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/middleware/rateLimit.ts)
  - dipasang ke `/admin/login`, `/merchant/login`, admin write routes, `/device`, dan `/integrations`.
- Env security baru:
  - `TRUST_PROXY`
  - `JSON_BODY_LIMIT`
  - `RATE_LIMIT_ENABLED`
  - `RATE_LIMIT_AUTH_WINDOW_MS`
  - `RATE_LIMIT_AUTH_MAX`
  - `RATE_LIMIT_ADMIN_WRITE_WINDOW_MS`
  - `RATE_LIMIT_ADMIN_WRITE_MAX`
  - `RATE_LIMIT_WRITE_WINDOW_MS`
  - `RATE_LIMIT_WRITE_MAX`
- Error code baru `RATE_LIMITED` di [src/shared/errors/index.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/errors/index.ts).

### 2. Audit, Monitoring, dan Logging

- Audit logging login admin:
  - `admin.login.success`
  - `admin.login.failed`
- Audit logging login merchant:
  - `merchant.login.success`
  - `merchant.login.failed`
- `auditLogStore` mendukung `actor_type: merchant`.
- Filter audit baru `action_contains` tersedia di:
  - [src/shared/store/auditLogStore.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/store/auditLogStore.ts)
  - [src/routes/admin.ts](/home/wira/work/codex/qris-soundbox-platform/src/routes/admin.ts)
- Admin audit UI sudah memakai real API, bukan mock:
  - [ui/admin-system-audit-logs/index.html](/home/wira/work/codex/qris-soundbox-platform/ui/admin-system-audit-logs/index.html)
- Audit UI memiliki filter action/entity/date/search, preset login events, KPI count, dan drawer JSON detail.
- Observability/health sebelumnya sudah tersedia:
  - `/health`
  - `/health/ready`
  - `/admin/observability/summary`
  - `/admin/observability/dead-letter-replays`
  - `/admin/observability/mqtt-status`

### 3. MQTT dan Device Operations

- MQTT worker dan policy production sudah diperketat.
- Wildcard subscribe default production dicegah oleh env check.
- MQTT ACL tooling tersedia:
  - `scripts/check-mqtt-acl.mjs`
  - `scripts/smoke-mqtt-acl.mjs`
  - `scripts/provision-mqtt-device.mjs`
- Package scripts:
  - `npm run mqtt:provision-device`
  - `npm run mqtt:check-acl`
  - `npm run smoke:mqtt-acl`
  - `npm run smoke:mqtt-real`
- Real MQTT smoke pernah pass dengan broker `mqtts://mqtt.iptek.co:8883`.

### 4. Settlement, Reconciliation, dan Finance Ops

- Settlement batch, merchant settlement history, reconciliation management, adjustment approval, dan device technical detail UI sudah tersedia.
- Admin reconciliation UI sudah menggunakan async export flow dan export history.
- Key UI pages:
  - [ui/admin-reconciliation-management/index.html](/home/wira/work/codex/qris-soundbox-platform/ui/admin-reconciliation-management/index.html)
  - [ui/settlement-batch-management/index.html](/home/wira/work/codex/qris-soundbox-platform/ui/settlement-batch-management/index.html)
  - [ui/merchant-settlement-history/index.html](/home/wira/work/codex/qris-soundbox-platform/ui/merchant-settlement-history/index.html)
  - [ui/device-technical-detail/index.html](/home/wira/work/codex/qris-soundbox-platform/ui/device-technical-detail/index.html)
- Placeholder `href="#"` sudah dibersihkan dari UI yang masuk QA.

### 5. Async Export dan Storage

- Async export job sudah tersedia untuk settlement adjustment export.
- Export job worker:
  - [src/shared/services/exportJobWorker.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/services/exportJobWorker.ts)
- Export job store:
  - [src/shared/store/exportJobStore.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/store/exportJobStore.ts)
- Migration:
  - [migrations/002_export_jobs.sql](/home/wira/work/codex/qris-soundbox-platform/migrations/002_export_jobs.sql)
  - [migrations/003_export_job_storage.sql](/home/wira/work/codex/qris-soundbox-platform/migrations/003_export_job_storage.sql)
- Export file storage memakai `EXPORT_STORAGE_DIR`, dengan metadata path/size/expiry.
- Export retention cleanup tersedia via worker.
- Admin endpoints:
  - `POST /admin/exports/settlement-adjustments`
  - `GET /admin/exports`
  - `GET /admin/exports/:jobId`
  - `GET /admin/exports/:jobId/download`

### 6. Deployment, Backup, Restore, dan Runbook

- Production env checker diperketat:
  - [scripts/check-production-env.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/check-production-env.mjs)
- Backup/restore tooling:
  - [scripts/backup-production.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/backup-production.mjs)
  - [scripts/restore-plan.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/restore-plan.mjs)
  - [scripts/restore-drill-validate.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/restore-drill-validate.mjs)
- Load testing/report tooling:
  - [scripts/load-test.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/load-test.mjs)
  - [scripts/run-staging-load-report.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/run-staging-load-report.mjs)
- Operational docs baru:
  - [OPERATIONAL_RUNBOOK.md](/home/wira/work/codex/qris-soundbox-platform/OPERATIONAL_RUNBOOK.md)
  - [PILOT_EXECUTION_CHECKLIST.md](/home/wira/work/codex/qris-soundbox-platform/PILOT_EXECUTION_CHECKLIST.md)
  - [EXPORT_STORAGE_READINESS.md](/home/wira/work/codex/qris-soundbox-platform/EXPORT_STORAGE_READINESS.md)
- README dan deployment readiness docs sudah direferensikan ke runbook/checklist tersebut.

## Endpoint Penting

- Health:
  - `GET /health`
  - `GET /health/ready`
- Admin auth/session:
  - `POST /admin/login`
  - `POST /admin/logout`
  - `GET /admin/me`
- Admin audit/observability:
  - `GET /admin/audit-logs`
  - `GET /admin/observability/summary`
  - `GET /admin/observability/dead-letter-replays`
  - `GET /admin/observability/mqtt-status`
- Admin export:
  - `POST /admin/exports/settlement-adjustments`
  - `GET /admin/exports`
  - `GET /admin/exports/:jobId`
  - `GET /admin/exports/:jobId/download`
- Merchant auth/session:
  - `POST /merchant/login`
  - `POST /merchant/logout`
  - `GET /merchant/me`
- Device and integration routes remain rate-limited for write-heavy paths:
  - `/device`
  - `/integrations`

## Package Scripts Penting

- `npm run typecheck`
- `npm run db:migrate`
- `npm run smoke:e2e`
- `npm run ui:qa`
- `npm run deploy:check-env`
- `npm run load:test`
- `npm run load:test:staging`
- `npm run backup:production`
- `npm run restore:plan`
- `npm run restore:validate`
- `npm run admin:create-user`
- `npm run merchant:create-user`
- `npm run mqtt:provision-device`
- `npm run mqtt:check-acl`
- `npm run smoke:mqtt-acl`
- `npm run smoke:mqtt-real`

## File Kunci yang Sering Disentuh

- App bootstrap: [src/app.ts](/home/wira/work/codex/qris-soundbox-platform/src/app.ts)
- Env config: [src/config/env.ts](/home/wira/work/codex/qris-soundbox-platform/src/config/env.ts)
- Admin routes: [src/routes/admin.ts](/home/wira/work/codex/qris-soundbox-platform/src/routes/admin.ts)
- Merchant routes: [src/routes/merchant.ts](/home/wira/work/codex/qris-soundbox-platform/src/routes/merchant.ts)
- Audit store: [src/shared/store/auditLogStore.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/store/auditLogStore.ts)
- Export worker: [src/shared/services/exportJobWorker.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/services/exportJobWorker.ts)
- Export store: [src/shared/store/exportJobStore.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/store/exportJobStore.ts)
- Rate limit middleware: [src/shared/middleware/rateLimit.ts](/home/wira/work/codex/qris-soundbox-platform/src/shared/middleware/rateLimit.ts)
- UI QA script: [scripts/ui-qa-check.mjs](/home/wira/work/codex/qris-soundbox-platform/scripts/ui-qa-check.mjs)
- Admin audit UI: [ui/admin-system-audit-logs/index.html](/home/wira/work/codex/qris-soundbox-platform/ui/admin-system-audit-logs/index.html)
- Env sample: [.env.example](/home/wira/work/codex/qris-soundbox-platform/.env.example)

## Decision Log Ringkas

- D-026 sampai D-049: dasar auth, merchant/admin flows, migration, UI awal, dan smoke testing.
- D-050 sampai D-059: production hardening awal, MQTT policy, finance/reconciliation UI, settlement flows.
- D-060 sampai D-069: merchant auth productionization, DB migration idempotent, monitoring/logging, load test, async export.
- D-070 sampai D-074: export storage/history, MQTT ACL, backup/restore, staging load report.
- D-075 sampai D-080: rate limiting/security polish, login audit, audit UI real data, UI QA cleanup, runbook/checklist produksi.

Rujukan utama: [DECISIONS_LOG.md](/home/wira/work/codex/qris-soundbox-platform/DECISIONS_LOG.md).

## Sisa Gap Utama

1. Eksekusi staging nyata dari checklist:
   - deploy dengan env final;
   - jalankan `deploy:check-env`, migration, smoke, UI QA, load report;
   - simpan artefak hasil staging.
2. Pilot real device:
   - provisioning device real;
   - validasi MQTT ACL per device;
   - transaksi QRIS test end-to-end;
   - validasi soundbox delivery dan dead-letter handling.
3. Restore drill nyata:
   - backup production/staging;
   - restore ke database disposable;
   - jalankan `restore:validate`;
   - dokumentasikan RTO/RPO aktual.
4. Export storage production topology:
   - pastikan `EXPORT_STORAGE_DIR` durable, absolute, writable, dan di-backup;
   - jika multi-node, perlu shared filesystem/object storage strategy.
5. Manual visual QA:
   - buka halaman admin utama di browser;
   - cek layout mobile/desktop;
   - cek login/session expiry state;
   - cek empty/error/loading state.
6. Operational readiness:
   - isi PIC, escalation contact, broker credential, backup location, dan pilot merchant list di runbook/checklist.

## Prioritas Lanjutan Disarankan

1. Jalankan full staging rehearsal dari `PILOT_EXECUTION_CHECKLIST.md`.
2. Lakukan manual visual QA admin UI dengan browser.
3. Jalankan restore drill sungguhan pada database disposable.
4. Finalisasi export storage production strategy.
5. Siapkan pilot real merchant/device dan rekam hasilnya di runbook.

## Catatan Penting

- Jangan hidupkan legacy auth di production.
- Jangan gunakan wildcard MQTT subscribe di production kecuali sedang maintenance terkontrol.
- `EXPORT_STORAGE_DIR` harus absolute path dan durable untuk production.
- Rate limiting sekarang aktif secara default jika `RATE_LIMIT_ENABLED=true`; hati-hati saat smoke test berulang pada login endpoint.
- `CODEX_HANDOFF.md` ini adalah snapshot operasional terbaru; untuk detail historis keputusan, baca `DECISIONS_LOG.md`.
