Compare commits

..

2 Commits

3 changed files with 303 additions and 104 deletions

View File

@ -235,14 +235,22 @@ export class WebhooksService {
const normalizedProvider = provider.toLowerCase();
const metaSignature = this.readHeader(headers['x-hub-signature-256']);
const genericSecret = this.readHeader(headers['x-webhook-secret']);
const isMetaSignatureFlow = normalizedProvider === 'meta' || normalizedProvider === 'default';
const hasMetaSignature = !!metaSignature;
if (normalizedProvider === 'meta' && config.appSecret) {
if (isMetaSignatureFlow && config.appSecret && hasMetaSignature) {
if (!rawBody || !metaSignature) {
throw new UnauthorizedException('Missing meta webhook signature');
}
verifyMetaSignature(rawBody, metaSignature, config.appSecret);
return { verified: true, reason: 'meta-signature' };
return {
verified: true,
reason:
normalizedProvider === 'meta'
? 'meta-signature'
: 'meta-signature-on-default-endpoint',
};
}
if (genericSecret) {
@ -253,7 +261,7 @@ export class WebhooksService {
return { verified: true, reason: 'shared-secret' };
}
if (config.allowUnsigned) {
if (config.allowUnsigned || !config.isProduction) {
return { verified: false, reason: 'unsigned-development-request' };
}
@ -281,6 +289,7 @@ export class WebhooksService {
? storedJson.appSecret
: env.metaWebhookAppSecret,
allowUnsigned: env.webhookAllowUnsigned,
isProduction: env.isProduction,
subscriptions:
Array.isArray(storedJson.subscriptions) && storedJson.subscriptions.length > 0
? storedJson.subscriptions.filter((item): item is string => typeof item === 'string')

View File

@ -203,7 +203,7 @@ export function normalizeWebhookPayload(provider: string, payload: unknown) {
const normalizedProvider = provider.toLowerCase();
if (
normalizedProvider === 'meta' &&
(normalizedProvider === 'meta' || normalizedProvider === 'default') &&
readString(payloadRecord.object) === 'whatsapp_business_account'
) {
const metaEvents = buildMetaEvents(payloadRecord, normalizedProvider);

View File

@ -1,136 +1,326 @@
# Codex Handoff
Snapshot tanggal: `2026-05-21`
Snapshot tanggal: `2026-05-22`
Dokumen ini dipakai untuk mempercepat pindah sesi kerja Codex tanpa perlu audit ulang dari nol.
Dokumen ini adalah ringkasan kondisi terakhir BizOne Portal supaya sesi Codex berikutnya bisa lanjut tanpa bongkar ulang dari nol.
## Ringkasan Cepat
- Repo: `bizone-portal`
- Branch aktif terakhir yang dicek: `main`
- Worktree tidak bersih
- Backend build: sukses
- Frontend build: sukses, dengan warning CSS compatibility
- Production readiness: belum siap, masih banyak blocker operasional dan integrasi
- Repo lokal: `/home/wira/work/codex/BizOne-portal`
- Repo server: `/srv/bizone-web`
- Branch: `main`
- Domain production: `https://portal.bizone.id`
- Backend production: `127.0.0.1:3001` via systemd `bizone-backend`
- Frontend production: `127.0.0.1:3000` via systemd `bizone-frontend`
- Meta webhook URL: `https://portal.bizone.id/api/webhooks/whatsapp`
- Midtrans notification URL: `https://portal.bizone.id/api/wallet/midtrans/notification`
## Worktree Saat Snapshot
Hasil `git status --short --branch` saat handoff dibuat:
## Commit Terakhir Lokal
```text
## main...origin/main
M deploy/debian12/app.env.example
?? public/
cc819ad Accept Midtrans dashboard notification tests
96b326e Fix roles page locale label typing
5144207 Prepare BizOne portal production wallet and UI
36be860 Add Codex handoff and update public assets
46ea32c Refresh session in contacts API proxy routes
```
File untracked yang terlihat:
Catatan penting:
- `public/favicon.ico`
- `public/bizone.png`
- Push dari environment Codex lokal gagal karena remote HTTPS butuh credential interaktif.
- User perlu menjalankan `git push origin main` dari terminal interaktif yang punya akses Git.
- Server sudah pernah melihat commit `96b326e`, tapi commit `cc819ad` perlu dipastikan sudah masuk remote/server sebelum test ulang Midtrans dashboard.
Jangan asumsi file di atas aman untuk dihapus. Verifikasi dulu apakah memang asset baru yang ingin dipakai.
## Status Git Auth
## Struktur Kerja Utama
Remote saat terakhir dicek:
- `backend/`: NestJS + TypeScript
- `frontend/`: Next.js 15 app router
- `prisma/`: schema dan migration
- `deploy/debian12/`: artefak deploy production Debian 12
- `PRODUCTION_CHECKLIST.md`: sumber status readiness production
```text
origin https://git.iptek.co/wirabasalamah/BizOne-portal.git
```
## Status Build Terakhir
Push dari Codex gagal dengan:
Perintah yang sudah diverifikasi:
```text
fatal: could not read Username for 'https://git.iptek.co': No such device or address
```
Solusi user:
```bash
cd backend && npm run build
cd frontend && npm run build
cd /home/wira/work/codex/BizOne-portal
git push origin main
```
Hasil:
- Backend compile sukses
- Frontend compile sukses dan generate static pages sukses
Warning frontend yang masih ada berasal dari `autoprefixer` pada [frontend/src/app/globals.css](/Users/wirabasalamah/Documents/Codex/bizone-portal/frontend/src/app/globals.css):
- line `3868`
- line `4681`
- line `7788`
- line `8399`
- line `8755`
Masalahnya penggunaan nilai seperti `start` atau `end` pada properti yang lebih aman memakai `flex-start` atau `flex-end`.
## Status Production Checklist
Snapshot dari [PRODUCTION_CHECKLIST.md](/Users/wirabasalamah/Documents/Codex/bizone-portal/PRODUCTION_CHECKLIST.md):
- Selesai: `35`
- Parsial: `5`
- Belum selesai: `39`
Area blocker utama sebelum production:
- staging final belum ada
- test Meta end-to-end belum dilakukan
- audit permission belum selesai
- CI/CD deploy flow belum final
- monitoring dan alerting belum aktif
- backup dan restore drill belum dibuktikan
- full smoke test lintas modul belum selesai
## Dokumen yang Perlu Dibaca Dulu
Urutan baca yang paling efisien untuk sesi baru:
1. [PRODUCTION_CHECKLIST.md](/Users/wirabasalamah/Documents/Codex/bizone-portal/PRODUCTION_CHECKLIST.md)
2. [README.md](/Users/wirabasalamah/Documents/Codex/bizone-portal/README.md)
3. [deploy/debian12/README.md](/Users/wirabasalamah/Documents/Codex/bizone-portal/deploy/debian12/README.md)
4. [backend/package.json](/Users/wirabasalamah/Documents/Codex/bizone-portal/backend/package.json)
5. [frontend/package.json](/Users/wirabasalamah/Documents/Codex/bizone-portal/frontend/package.json)
## Command Cepat Untuk Re-Orientasi
Atau pakai username:
```bash
git status --short --branch
sed -n '1,220p' PRODUCTION_CHECKLIST.md
cd backend && npm run build
cd frontend && npm run build
git push https://wira.irawan%40gmail.com@git.iptek.co/wirabasalamah/BizOne-portal.git main
```
Kalau perlu cek warning CSS:
Jangan taruh token di command kalau tidak perlu, karena bisa masuk shell history.
## Fitur Besar Yang Sudah Masuk
- Redesign login, dashboard shell, sidebar, card spacing, dan halaman utama dashboard.
- Dual bahasa `EN/ID` diperluas ke banyak halaman.
- Global search di header.
- Notification center di header.
- Help page dari icon `?`.
- Profile menu dan halaman profile user.
- Wallet/saldo untuk broadcast.
- Minimum top up `Rp50.000`.
- Preset top up `50rb`, `100rb`, `250rb`, `500rb`, `1jt`.
- Harga broadcast sementara `Rp500` per pesan.
- Broadcast hanya cek saldo sebelum kirim, saldo dipotong setelah worker memproses pesan sukses.
- Integrasi Midtrans Snap API awal.
- Midtrans payment methods: `gopay`, `shopeepay`, `bank_transfer`, `credit_card`.
- Midtrans notification webhook.
- Production deploy docs untuk `portal.bizone.id`.
- Root `/` redirect ke `/login`, tidak lagi menampilkan starter landing page.
## Midtrans Status Terakhir
URL final yang harus dipakai di dashboard Midtrans:
```text
https://portal.bizone.id/api/wallet/midtrans/notification
```
Server internal test sudah pernah menghasilkan response ini setelah route aktif:
```json
{"message":"Invalid Midtrans notification signature.","error":"Bad Request","statusCode":400}
```
Itu normal untuk payload kosong.
Dashboard Midtrans test notification mengirim payload seperti:
```json
{
"transaction_status": "settlement",
"status_code": "200",
"signature_key": "...",
"payment_type": "gopay",
"order_id": "payment_notif_test_G311975080_...",
"merchant_id": "G311975080",
"gross_amount": "105000.00"
}
```
Karena `order_id` test tidak ada di tabel `payment_orders`, backend awalnya menolak. Commit `cc819ad` memperbaiki ini:
- Signature tetap divalidasi.
- Kalau `order_id` diawali `payment_notif_test_` dan `merchant_id` cocok dengan `MIDTRANS_MERCHANT_ID`, backend return `200`.
- Transaksi asli tetap wajib punya payment order.
Setelah commit `cc819ad` dipull ke server, jalankan:
```bash
nl -ba frontend/src/app/globals.css | rg '\b(start|end)\b'
cd /srv/bizone-web
git pull
set -a
source .env
set +a
cd backend
NODE_ENV=development npm ci
npm run db:generate
npm run build
npm run db:migrate:deploy
sudo systemctl restart bizone-backend
```
## Prioritas Kerja Berikutnya
Lalu test:
Urutan yang paling masuk akal untuk dilanjutkan:
```bash
curl -i -X POST https://portal.bizone.id/api/wallet/midtrans/notification \
-H "Content-Type: application/json" \
-d '{}'
```
1. Rapikan warning CSS di `frontend/src/app/globals.css` lalu build ulang frontend.
2. Audit perubahan di `deploy/debian12/app.env.example` dan putuskan apakah mau di-commit.
3. Putuskan status folder `public/` apakah asset final atau artefak lokal.
4. Pecah `PRODUCTION_CHECKLIST.md` menjadi task implementasi teknis yang bisa dikerjakan satu per satu.
5. Fokuskan sprint berikut ke salah satu jalur:
- jalur infra: staging, backup, monitoring, CI/CD
- jalur product integration: Meta webhook dan outbound live test
- jalur app hardening: permission audit dan smoke test
Payload kosong boleh tetap `400 Invalid Midtrans notification signature`; test dashboard Midtrans yang signed harus `200` setelah commit `cc819ad` aktif di server.
## Catatan Kerja
## Midtrans Env Production/Server
- Root `package.json` hanya dipakai untuk dependency Prisma bersama.
- Backend local run yang disarankan oleh repo: `cd backend && npm run local`
- Frontend local run: `cd frontend && npm run dev`
- Deploy production yang didokumentasikan menargetkan `https://portal.bizone.id`
- Ada perbedaan konsep URL backend di dokumen deploy: browser-facing route memakai `/api`, sementara backend internal juga diekspos lewat `/backend-api`. Jangan ubah ini tanpa cek alur Next route handler lebih dulu.
User menunjukkan dashboard Midtrans `Environment Sandbox`, tapi key formatnya tetap:
## Definition Of Done Untuk Sesi Lanjutan
```text
Mid-client-...
Mid-server-...
```
Sesi baru sebaiknya selalu menutup kerja dengan:
Jadi jangan lagi mengasumsikan sandbox pasti `SB-Mid-*` untuk akun ini. Yang penting key di `/srv/bizone-web/.env` sama dengan dashboard Midtrans yang dipakai.
- build ulang area yang diubah
- update dokumen status bila ada perubahan readiness
- catat blocker nyata, bukan asumsi
- pastikan `git status` jelas sebelum handoff berikutnya
Contoh env server saat terakhir dibahas:
```dotenv
MIDTRANS_ENV=sandbox
MIDTRANS_SERVER_KEY=Mid-server-...
MIDTRANS_CLIENT_KEY=Mid-client-...
MIDTRANS_MERCHANT_ID=G311975080
MIDTRANS_ALLOWED_PAYMENT_TYPES=gopay,shopeepay,bank_transfer,credit_card
```
Jangan commit `.env`.
## Server Deploy Notes
Jika backend build gagal dengan:
```text
sh: 1: tsc: not found
```
Penyebab: `NODE_ENV=production npm ci` tidak memasang devDependencies. Pakai:
```bash
NODE_ENV=development npm ci
```
Jika backend build gagal dengan banyak error Prisma seperti:
```text
Property 'sql' does not exist on type 'typeof Prisma'
Module '@prisma/client' has no exported member 'Campaign'
```
Penyebab: Prisma client stale setelah `npm ci`. Urutan benar:
```bash
cd /srv/bizone-web
npm install
cd backend
NODE_ENV=development npm ci
npm run db:generate
npm run build
```
Setelah build:
```bash
npm run db:migrate:deploy
sudo systemctl restart bizone-backend
```
Cek route wallet:
```bash
sudo journalctl -u bizone-backend -n 200 --no-pager | grep -i wallet
```
Harus ada:
```text
WalletController {/api/wallet}
Mapped {/api/wallet/topups/midtrans, POST}
WalletMidtransWebhookController {/api/wallet/midtrans}
Mapped {/api/wallet/midtrans/notification, POST}
```
## Nginx Production
Config nginx yang user kirim sudah benar untuk Midtrans dan Meta:
```nginx
location /api/webhooks/ {
proxy_pass http://127.0.0.1:3001/api/webhooks/;
}
location /api/wallet/midtrans/ {
proxy_pass http://127.0.0.1:3001/api/wallet/midtrans/;
}
location /backend-api/ {
proxy_pass http://127.0.0.1:3001/api/;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
```
Kalau public endpoint `502`, cek backend/frontend service. Kalau internal backend `404`, berarti backend build belum memuat route baru.
## Credential Dev/Admin
Default seed admin:
```text
Email: admin@bizone.id
Password: ChangeMe123!
```
Jika server login gagal, reset seed:
```bash
cd /srv/bizone-web/backend
set -a
source ../.env
set +a
npm run seed:admin
```
Setelah production login pertama, ganti password dan aktifkan 2FA.
## Files Penting Yang Diubah
Backend:
- `backend/src/wallet/*`
- `backend/src/app.module.ts`
- `backend/src/campaigns/campaigns.service.ts`
- `backend/src/campaigns/campaigns.controller.ts`
- `backend/src/common/permission.guard.ts`
- `backend/src/auth/*`
- `prisma/schema.prisma`
- `prisma/migrations/0015_wallet/migration.sql`
Frontend:
- `frontend/src/app/dashboard/wallet/page.tsx`
- `frontend/src/components/wallet-topup-form.tsx`
- `frontend/src/components/dashboard-shell.tsx`
- `frontend/src/components/global-search-button.tsx`
- `frontend/src/components/notification-center.tsx`
- `frontend/src/components/profile-menu.tsx`
- `frontend/src/components/profile-forms.tsx`
- `frontend/src/app/dashboard/help/page.tsx`
- `frontend/src/app/dashboard/profile/page.tsx`
- `frontend/src/app/page.tsx`
- `frontend/src/app/globals.css`
- banyak halaman dashboard untuk spacing dan dual bahasa.
Deploy docs:
- `deploy/debian12/app.env.example`
- `deploy/debian12/nginx.portal.bizone.id.conf`
- `deploy/debian12/README.md`
- `PRODUCTION_CHECKLIST.md`
- `PRODUCTION_READINESS.md`
- `docs/production-server-checklist.md`
## Next Steps Paling Dekat
1. Push commit `cc819ad` ke remote.
2. Pull di server.
3. Rebuild backend dengan urutan Prisma yang benar.
4. Restart `bizone-backend`.
5. Test ulang Midtrans notification URL dari dashboard Midtrans.
6. Rebuild frontend jika ada perubahan UI baru.
7. Jalankan smoke test:
- buka `https://portal.bizone.id`
- login admin
- buka wallet
- buat top up Midtrans
- cek payment order dan saldo setelah notification sukses.
## Catatan Keamanan
- `.env` sudah di-ignore dan tidak ikut commit.
- Beberapa credential pernah muncul di chat/screenshot, jadi untuk production live sebaiknya rotate credential final.
- `deploy/debian12/app.env.example` sudah dibersihkan agar hanya berisi placeholder.