feat: add Queue-based server provisioning with security fixes

- Add Cloudflare Queue for async server provisioning
  - Producer: callback-handler.ts sends to queue
  - Consumer: provision-consumer.ts processes orders
  - DLQ: provision-dlq.ts handles failed orders with refund

- Security improvements (from code review):
  - Store password hash instead of plaintext (SHA-256)
  - Exclude root_password from logs
  - Add retryable flag to prevent duplicate instance creation
  - Atomic balance deduction with db.batch()
  - Race condition prevention with UPDATE...WHERE status='pending'
  - Auto-refund on DLQ processing

- Validation improvements:
  - OS image whitelist validation
  - Session required fields validation
  - Queue handler refactoring

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-24 22:54:15 +09:00
parent 2494593b62
commit 1fead51eff
7 changed files with 488 additions and 87 deletions

View File

@@ -74,3 +74,26 @@ crons = ["0 15 * * *"] # UTC 15:00 = KST 00:00
# - LINODE_API_KEY: Linode Personal Access Token
# - VULTR_API_KEY: Vultr API Key
# - SERVER_ADMIN_ID: 서버 관리 알림 수신자 Telegram ID
# ============================================
# Queue Configuration (Server Provisioning)
# ============================================
# Queue Producer 바인딩
[[queues.producers]]
queue = "server-provision-queue"
binding = "SERVER_PROVISION_QUEUE"
# Queue Consumer 바인딩 (같은 Worker에서 처리)
[[queues.consumers]]
queue = "server-provision-queue"
max_retries = 3
max_batch_size = 1
max_batch_timeout = 30
max_concurrency = 3
dead_letter_queue = "provision-dlq"
# Dead Letter Queue Consumer
[[queues.consumers]]
queue = "provision-dlq"
max_retries = 0