# Deployment Readiness

## Production Preflight

Debian 12 app server setup untuk domain `sms.bizone.id` tersedia di `DEBIAN12_APP_SERVER_SETUP.md`.

Run this before deploying a production candidate:

```bash
npm run typecheck
npm run db:migrate
npm audit
npm run smoke:e2e
npm run deploy:check-env
npm run mqtt:check-acl -- --file /etc/mosquitto/acl
```

Use `npm run smoke:mqtt-real` separately after Mosquitto ACL, backend credential, and broker networking are ready.
Use `npm run smoke:mqtt-acl` with two provisioned device credentials before hardware pilot.

## Required Production Controls

- Create production admin users with `npm run admin:create-user -- --email <email> --name <name> --role <role> --password <strong-password>`.
- Create merchant portal users with `npm run merchant:create-user -- --merchant <merchant-id-or-code> --email <email> --name <name> --role <role> --password <strong-password>`.
- Set `ADMIN_DEV_LOGIN_ENABLED=false`.
- Set `ADMIN_AUTH_ALLOW_LEGACY_TOKEN=false` after admin users and roles are configured.
- Set `MERCHANT_DEV_LOGIN_ENABLED=false`.
- Set `MERCHANT_AUTH_ALLOW_LEGACY_TOKEN=false` after merchant portal users are configured.
- Set `DEVICE_AUTH_ALLOW_LEGACY_TOKEN=false` after all devices use per-device credentials.
- Set `ADMIN_SESSION_SECRET`, `INTEGRATION_WEBHOOK_SECRET`, `MQTT_PASSWORD`, and database credentials to strong non-default values.
- Set `MQTT_PUBLISH_MODE=broker`.
- Set `MQTT_SUBSCRIBE_ENABLED=true` when broker uplink observability is needed.
- Keep `EXPORT_WORKER_ENABLED=true` for async export processing, or run a dedicated app instance with the worker enabled.
- Set `EXPORT_STORAGE_DIR` to a backed-up writable directory and set `EXPORT_RETENTION_DAYS` according to finance retention needs.
- Use an absolute `EXPORT_STORAGE_DIR`; see `EXPORT_STORAGE_READINESS.md` for single-node vs multi-node notes.
- Keep `RATE_LIMIT_ENABLED=true` and tune rate limit env values for expected pilot traffic.
- Set `TRUST_PROXY=true` when behind a reverse proxy/load balancer.
- Set `JSON_BODY_LIMIT` to the smallest practical request body limit.
- Set `SETTLEMENT_ADJUSTMENT_REQUIRE_APPROVAL=true` for finance approval control.

## Operational Checks

- Confirm `/health`, `/admin/health`, and `/admin/mqtt/status`.
- Confirm `/health/deep` and `/admin/health/deep` for DB/MQTT readiness.
- Confirm `/admin/observability/summary` for notification failure, settlement mismatch, DB, and MQTT summary.
- Confirm async export worker status in `/admin/observability/summary`.
- Confirm async export job flow with `POST /admin/exports/settlement-adjustments`, polling `GET /admin/exports/:jobId`, and download.
- Confirm export files are written under `EXPORT_STORAGE_DIR` and expire after retention.
- Run `npm run backup:production -- --dry-run` and one real backup before pilot.
- Run `npm run restore:plan -- --backup <dump>` and perform a restore drill on a disposable database.
- After restore drill, run `npm run restore:validate` against the restored service.
- Run staging load profile with `npm run load:test:staging` against a production-like environment.
- Run `npm run ui:qa`.
- Set `LOG_FORMAT=json` and ship stdout/stderr to the production log collector.
- Confirm Postgres backup/restore procedure and retention.
- Confirm Mosquitto password file and ACL are backed up.
- Confirm logs include `request_id` for admin, device, and integration paths.
- Confirm settlement CSV export format with the target bank/payment rail before live payout operations.
- Keep `OPERATIONAL_RUNBOOK.md` and `PILOT_EXECUTION_CHECKLIST.md` available to the operator on duty.
