11 KiB
11 KiB
Codex Handoff - QRIS Soundbox Platform
Tanggal update: 2026-06-03, Asia/Jakarta.
Dokumen ini adalah snapshot kerja terakhir untuk melanjutkan project tanpa perlu membaca ulang seluruh chat.
Status Terakhir
- Fokus hari ini bergeser dari production readiness umum ke integrasi device soundbox QF100.
- Folder SDK lokal
QF100-60s-l511-SecondApp-260107/ditemukan dan dianalisis. Folder ini sengaja tidak dimasukkan git. - Backend sekarang sudah punya adapter awal untuk firmware QF100 sample:
- config server vendor-compatible;
- payload MQTT payment success format QF100;
- smoke script backend untuk static + dynamic QF100.
- Target milestone berikutnya: dua soundbox real, satu static dan satu dynamic, bisa ambil config dari backend, connect MQTT, lalu static payment test bunyi dan tercatat di dashboard.
- Worktree aktif/dirty karena perubahan backend QF100 dan update handoff. Jangan revert perubahan yang tidak eksplisit diminta.
Verifikasi Terakhir
npm run typecheck: pass setelah perubahan QF100.npm install: sudah dijalankan untuk memasang dependency lokal; perubahan lockfile accidental sudah dibalik.npm run smoke:qf100: script sudah dibuat, belum dijalankan end-to-end di DB/server lokal pada turn ini.- Verifikasi lama yang masih relevan:
npm run db:migrate: sebelumnya pass dan idempotent sampai migration003_export_job_storage.sql.npm audit --json: sebelumnya pass, 0 vulnerability.npm run ui:qa: sebelumnya pass.npm run smoke:e2e: sebelumnya pass.- Real MQTT smoke sebelumnya pernah pass terhadap
mqtts://broker.bizone.id:8883.
SDK QF100 Yang Ditemukan
- Folder lokal:
QF100-60s-l511-SecondApp-260107/. - Sudah ditambahkan ke
.gitignore:QF100-60s-l511-SecondApp-260107/
- Struktur penting:
docs/Config Server.docx: kontrak config server vendor.docs/Cloud Speaker API Spec V2.8.7.pdf: API spec cloud speaker.app/source/MainApp/globalDefine.h: device model, demo mode,CONFIG_ADDR.app/source/MainApp/demo.c: alur config server, MQTT connect/subscribe, parse payment payload.app/source/MainApp/demo.h: MQTT TLS/QoS/clean session/cert config.app/source/MainApp/main.c: boot flow dan monitor network/MQTT.app/inc/MercuryMqtt.h: header MQTT SDK.app/release/user_app.bin: firmware build existing.
Kesimpulan SDK QF100
- SDK ini memungkinkan develop/patch aplikasi firmware sendiri, tetapi bentuknya embedded C firmware app, bukan SDK backend.
- Strategi dipilih: firmware hanya hardcode URL config server backend kita, bukan hardcode broker MQTT.
- Firmware sample boot lalu call
CONFIG_ADDRke endpoint vendor/speaker/dev-config. - Request config berisi field seperti:
dev-modelitem-numberdev-snfw-versionfw-buildapp-config-versionimeiimsiiccid
- Response yang firmware cari memiliki blok:
mqtt.broker-ipmqtt.broker-portmqtt.client-idmqtt.user-namemqtt.passwordmqtt.subscribe-topicmqtt.keep-alive
- Payment success payload yang firmware sample bisa bunyikan:
{ "header": { "category": 1 }, "data": { "pay-amount": 15000 } } MQTT_TLS_ENABLEdi SDK sample masih0. Jika broker production memakaimqtts://...:8883, firmware perlu patch TLS atau pilot perlu listener non-TLS terbatas.
Implementasi QF100 Backend Hari Ini
1. Config Server Vendor-Compatible
- Route baru:
GET /speaker/dev-config
- File:
src/routes/speaker.ts- mounted di
src/app.ts
- Perilaku:
- menerima query/body vendor;
- lookup device memakai
dev-sn->devices.serial_number; - jika device aktif, update:
vendormodelcommunication_modelast_seen_atfirmware_version
- mencatat heartbeat
state: config_pull; - balas JSON vendor top-level, bukan wrapper internal
successResponse.
- Error vendor style:
1001:dev-snkosong;1002: device tidak terdaftar atau inactive;1003: broker MQTT belum dikonfigurasi.
2. Env QF100
- Env baru di
src/config/env.tsdan.env.example:QF100_MQTT_BROKER_HOSTQF100_MQTT_BROKER_PORTQF100_MQTT_USERNAMEQF100_MQTT_PASSWORDQF100_MQTT_KEEP_ALIVE_SECONDS
- Jika host/port QF100 kosong, endpoint mencoba parse dari
MQTT_BROKER_URL. - Catatan penting: password MQTT yang dikirim ke QF100 diambil dari
QF100_MQTT_PASSWORDatau fallbackMQTT_PASSWORD. Sistem saat ini menyimpan credential device sebagai fingerprint, jadi plaintext per-device tidak bisa dibaca ulang dari DB.
3. Payload MQTT QF100
- File:
src/shared/services/mqttPublisher.tssrc/shared/orchestrators/notificationOrchestrator.ts
- Topic QF100:
devices/{deviceId}/downlink/qf100
- Adapter memilih format QF100 jika:
device.modelmengandungQF100; ataucapability_profile_json.mqtt_payload_profile,protocol_profile, atauvendor_protocolbernilaiqf100.
- Downlink payment sekarang juga dicatat ke
mqtt_messages, sehingga dashboard device detail bisa melihat topic/payload yang dikirim.
4. Device Store dan Schema
- Lookup baru:
getDeviceBySerialNumber(serialNumber)disrc/shared/store/deviceStore.ts.
- Schema bootstrap menambahkan index:
idx_devices_serial_number.
5. Smoke QF100
- Script baru:
scripts/smoke-qf100-adapter.mjs
- Package script baru:
npm run smoke:qf100
- Script ini:
- create merchant/outlet/terminal/device static;
- create merchant/outlet/terminal/device dynamic MQTT;
- set
model: QF100dancapability_profile_json.mqtt_payload_profile: qf100; - hit
/speaker/dev-configuntuk dua SN; - validasi MQTT config vendor;
- trigger static QRIS paid callback;
- validasi
mqtt_messagesdownlink QF100 payloadcategory: 1; - trigger backend dynamic QR MQTT flow untuk device dynamic.
- Untuk memakai SN real:
QF100_STATIC_SN=<sn-static> \ QF100_DYNAMIC_SN=<sn-dynamic> \ BASE_URL=http://127.0.0.1:3000 \ npm run smoke:qf100
Device Flow Yang Disepakati
Static Soundbox
- Device boot.
- Firmware call backend
/speaker/dev-config. - Backend balas MQTT config.
- Device connect MQTT dan subscribe
devices/{deviceId}/downlink/qf100. - QRIS callback paid masuk backend.
- Backend publish payload QF100
category: 1. - Device bunyi nominal.
- Dashboard melihat transaction, notification, mqtt message, last seen/config pull.
Dynamic Soundbox
- Prinsip: trigger tetap via MQTT, bukan polling terus-menerus.
- HTTP polling dynamic QR dianggap tidak cocok untuk skala 20 ribu device karena
gap=30sberarti sekitar 40 ribu request/menit. - Desain lanjutan:
- Backend/admin/merchant membuat dynamic QR request.
- Backend publish MQTT command ke device.
- Device menampilkan QR langsung atau HTTP fetch QR detail dari URL.
- Payment callback tetap jadi source of truth.
- Payment success tetap via MQTT
category: 1.
- Firmware dynamic handler belum dipatch. Perlu tambah handler misalnya
category == 10didemo.c.
Dashboard Yang Perlu Disiapkan Berikutnya
Prioritas UI/dashboard untuk test dua soundbox real:
- Device detail QF100 panel:
- SN;
- model/profile;
- config pull terakhir;
- broker host/port yang dikirim;
- client-id;
- subscribe-topic;
- keepalive.
- Test payment button:
- nominal quick actions, misalnya Rp1.000 dan Rp15.000;
- create dummy tx/callback internal;
- tampilkan notification dan MQTT payload result.
- MQTT timeline:
- direction;
- topic;
- message_type;
- payload JSON;
- publish_status/reason;
- timestamp.
- Dynamic QR panel:
- input nominal;
- create dynamic QR;
- tampilkan QR payload/status;
- nanti
Send to Soundboxvia MQTT command setelah firmware handler siap.
- Ops summary:
- total soundbox;
- online/stale/offline;
- config pull terbaru;
- payment notification sent/failed;
- dynamic QR active/paid/expired.
Endpoint Penting Saat Ini
- Health:
GET /healthGET /health/deep
- QF100 vendor config:
GET /speaker/dev-config
- Admin auth/session:
POST /admin/loginPOST /admin/logoutGET /admin/me
- Admin device:
POST /admin/devicesGET /admin/devicesGET /admin/devices/{id}POST /admin/devices/{id}/credentials/rotatePOST /admin/devices/{id}/bindPOST /admin/devices/{id}/unbindGET /admin/devices/{id}/mqtt-messagesGET /admin/devices/{id}/notifications
- Device API:
POST /device/heartbeatPOST /device/transactions/dynamic-qrPOST /device/mqtt/uplink/dynamic-qr/requestGET /device/configPOST /device/config/ack
- Integrations:
POST /integrations/qris/callback
- Observability:
GET /admin/observability/summaryGET /admin/observability/mqtt-status
Package Scripts Penting
npm run typechecknpm run db:migratenpm run smoke:qf100npm run smoke:e2enpm run smoke:mqtt-realnpm run smoke:mqtt-aclnpm run ui:qanpm run deploy:check-envnpm run load:testnpm run load:test:stagingnpm run mqtt:provision-devicenpm run mqtt:check-aclnpm run admin:create-usernpm run merchant:create-user
File Kunci Yang Sering Disentuh
- App bootstrap:
src/app.ts - Env config:
src/config/env.ts - QF100 config route:
src/routes/speaker.ts - Device route:
src/routes/device.ts - Admin route:
src/routes/admin.ts - MQTT publisher:
src/shared/services/mqttPublisher.ts - MQTT subscriber:
src/shared/services/mqttSubscriber.ts - Notification orchestrator:
src/shared/orchestrators/notificationOrchestrator.ts - Device store:
src/shared/store/deviceStore.ts - MQTT message store:
src/shared/store/mqttMessageStore.ts - Heartbeat store:
src/shared/store/heartbeatStore.ts - Schema bootstrap:
src/shared/db/pool.ts - QF100 smoke:
scripts/smoke-qf100-adapter.mjs - Env sample:
.env.example
Sisa Gap Utama
- Jalankan
npm run smoke:qf100terhadap backend + DB lokal/staging. - Register dua device real:
- static SN -> device static;
- dynamic SN -> device dynamic.
- Patch firmware QF100:
CONFIG_ADDRke backend kita;- TLS setting sesuai broker.
- Test static device real:
- config pull;
- MQTT connect;
- payment success bunyi;
- dashboard melihat downlink.
- Patch firmware dynamic:
- tambah handler command dynamic QR, kemungkinan
category == 10; - pilih direct QR payload vs HTTP fetch detail.
- tambah handler command dynamic QR, kemungkinan
- Siapkan dashboard QF100 detail/test panel.
- Putuskan credential strategy production:
- shared pilot password saat ini cukup untuk lab;
- production sebaiknya credential per-device yang bisa diprovisioning aman.
- Tetap perlu staging rehearsal, restore drill, export storage strategy, dan manual visual QA dari handoff lama.
Catatan Penting
- Folder SDK QF100 adalah artefak lokal dan jangan dimasukkan git.
- Jangan hardcode broker credential production di firmware.
- Firmware cukup hardcode config server URL; broker/topic/credential dikirim dari backend.
- Jangan gunakan wildcard MQTT subscribe di production kecuali maintenance terkontrol.
- Jika memakai MQTT TLS (
mqtts://...:8883), firmware QF100 perluMQTT_TLS_ENABLE=1dan sertifikat yang sesuai. - Rate limiting aktif default;
/speakermemakai limiter device. CODEX_HANDOFF.mdini adalah snapshot operasional terbaru; untuk detail historis keputusan, bacaDECISIONS_LOG.md.