security: fix CSRF/ownership/timing vulns; add billing reconciliation

- auth/guard: добавить CSRF-проверку Origin/Referer для cookie-мутаций,
  исправить инвертированную логику admin_guard (пускал всех, блокировал админов),
  перевести admin_guard на from_fn_with_state
- auth/service: timing-safe сравнение HMAC через verify_slice вместо != по hex;
  криптостойкий Seed через Alphanumeric (был цифровой 0-9)
- billing: confirm_payment проверяет owner (caller_id == invoice.user_id);
  активация триала только для Telegram-аккаунтов (Sybil-защита);
  реализована reconcile_pending_payments — сверка blockchain->pending-инвойсы
- billing/providers: get_recent_transactions перенесён в трейт PaymentProvider
- nodes/service: unwrap() -> map_err по всему SSH-пути; убран TcpStream import
- docker: multi-stage build с cargo-chef, non-root user, healthcheck;
  prod-compose добавляет one-shot migrate-сервис, убирает проброс порта БД
- deploy.yml: параметр image_tag, set -e, pull всего стека вместо только app
- users/service: обработка NO_TICKETS / NO_USER из БД вместо catch-all

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Kirill
2026-06-29 17:58:24 +07:00
parent 26d6f2db8a
commit f06cc48763
19 changed files with 605 additions and 177 deletions
+2 -2
View File
@@ -50,13 +50,13 @@ async fn initiate_payment_api(
/// Шаг 2: Подтверждаем транзакцию после того как юзер её оплатил
async fn confirm_payment_api(
Extension(_user): Extension<User>, // В будущем можно сверять ID юзера с инвойсом
Extension(user): Extension<User>,
State(state): State<ApiState>,
Json(payload): Json<ConfirmPaymentPayload>,
) -> Result<Json<Value>, AppError> {
state
.billing_service
.confirm_payment(payload.invoice_id, &payload.external_tx_id)
.confirm_payment(user.id, payload.invoice_id, &payload.external_tx_id)
.await?;
Ok(Json(json!({