# Server PUBLIC_PORT=3000 INTERNAL_PORT=3001 INTERNAL_HOST=127.0.0.1 # Database DATABASE_URL=postgresql://user:password@localhost:5432/halobestie # Valkey / Redis VALKEY_URL=redis://localhost:6379 # Control center origin (for CORS + refresh-cookie). Comma-separated list allowed. CC_ORIGIN=http://localhost:5173 # --- Auth (Phase 3.4) --- # JWT access token signing key (HS256). Must be >= 32 chars. AUTH_JWT_SECRET=replace-with-strong-random-32+char-secret ACCESS_TOKEN_TTL_SECONDS=3600 REFRESH_TOKEN_TTL_DAYS=30 # Fazpass (OTP provider — TBD real values once docs are available) FAZPASS_API_KEY= FAZPASS_BASE_URL= FAZPASS_WEBHOOK_SECRET= # Google OAuth — comma-separated list of valid audience client IDs (Android, iOS). GOOGLE_OAUTH_CLIENT_IDS= # Apple Sign In APPLE_SERVICES_ID= APPLE_TEAM_ID= APPLE_KEY_ID= APPLE_PRIVATE_KEY= # First super-admin (used by seed script) ADMIN_EMAIL=admin@halobestie.com ADMIN_PASSWORD=ChangeMe123! # --- FCM (kept — only Messaging is used; Auth is self-managed) --- # Path to Firebase service-account JSON (falls back to backend/firebase-service-account.json) FIREBASE_SERVICE_ACCOUNT_PATH= # --- Valkey availability mirror cadences --- # # All env-driven per backend/CLAUDE.md Config-Source Convention. Defaults match # requirement/valkey-online-mirror-plan.md. Floor-clamped by their getters. # How often the auto-offline sweep checks heartbeat freshness (seconds). # The staleness threshold itself (`stale_after_seconds`) is CC-tunable via app_config. MITRA_AUTO_OFFLINE_SWEEP_SECONDS=30 # How often heartbeat timestamps are batched from Valkey → Postgres (seconds). # Per-ping heartbeat writes go to Valkey only; this preserves forensic # `last_heartbeat_at` in Postgres with up to seconds of lag. HEARTBEAT_MIRROR_INTERVAL_SECONDS=60 # How often Valkey state is re-derived from Postgres to heal drift (seconds). # Belt-and-braces against failed best-effort Valkey writes, out-of-band Postgres # mutations, or evictions. Set to 0 to disable (not recommended). VALKEY_ONLINE_MIRROR_SWEEP_SECONDS=300 # --- Phase 5: Xendit (dev-safe defaults: integration disabled) --- # # Flip XENDIT_ENABLED=true in staging/prod once secret + webhook token are populated. # When false, payment.service.js skips invoice creation and the dev/Maestro stub # /internal/_test/force-confirm-payment plays the role of the webhook. # See requirement/phase5-xendit-plan.md. XENDIT_ENABLED=false XENDIT_SECRET_KEY= XENDIT_WEBHOOK_TOKEN= XENDIT_SUCCESS_REDIRECT_URL= XENDIT_FAILURE_REDIRECT_URL= # --- Xendit webhook survival sink (optional file-based fallback) --- # # When the primary DB log (`webhook_logs` table) is unreachable, the route can # spill each inbound webhook to a daily-rolling JSONL file instead. Disabled # by default — production opts in by mounting a persistent volume / GCS sync # and flipping XENDIT_WEBHOOK_FALLBACK_ENABLED=true. The handler will NOT # fall back to stdout; if both DB and this sink are unavailable the event is # dropped. # # Filename pattern: "-YYYY-MM-DD.jsonl" (UTC day boundary). XENDIT_WEBHOOK_FALLBACK_ENABLED=false XENDIT_WEBHOOK_FALLBACK_DIR=./logs XENDIT_WEBHOOK_FALLBACK_NAME=xendit-webhook-fallback