Files
netrunner-backend/Cargo.toml
T
nineap d91aef012e
Build & Push Image / Build and push Caddy (Cloudflare DNS) image (push) Successful in 26s
Build & Push Image / Build and push to Gitea Registry (push) Successful in 9m36s
CI / fmt + clippy + test (push) Failing after 24m37s
Region-aware pricing: GeoIP + VPN-детект + публичный /plans + бот
- modules::geoip — DB-IP Lite (.mmdb, без регистрации/ключа, в отличие от
  MaxMind) для страны по IP, X4BNet lists_vpn для грубой VPN/датацентр-
  эвристики. Обе базы скачиваются в рантайме, обновление — фоновая
  задача в tasks.rs (раз в сутки по умолчанию, GEOIP_REFRESH_INTERVAL).
- GET /api/v1/billing/plans (public_router, без auth_guard) — цены в
  валюте, определённой по IP посетителя (X-Real-IP/X-Forwarded-For,
  см. nginx-конфиги). VPN/датацентр IP -> всегда базовый USD, чтобы
  обход региона через любой публичный VPN не обесценивал скидки.
- Бот: Bot API не отдаёт IP пользователя вообще — валюта определяется по
  Telegram language_code. Показ цены — в валюте региона, САМА оплата
  через CryptoBot остаётся в USD/USDT (провайдер биллит 1:1 к USD-цене
  тарифа, менять валюту списания нельзя, не меняя сам провайдер).
2026-07-11 00:55:03 +07:00

57 lines
2.2 KiB
TOML

[package]
name = "netrunner-control-plane"
version = "0.2.0"
edition = "2021"
[dependencies]
tokio = { version = "1.40", features = ["full"] }
axum = { version = "0.8.9", features = ["macros"] }
tower = "0.5.3"
tower-http = { version = "0.6.8", features = ["fs", "trace", "cors"] }
tower_governor = "0.8"
teloxide = { version = "0.17", features = ["macros", "rustls"] }
# 🔥 ИСПРАВЛЕНО: Включаем "migrate" для автоматического создания баз в тестах
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "uuid", "chrono", "migrate", "rust_decimal"] }
redis = { version = "1.2.0", features = ["tokio-comp", "aio", "connection-manager"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.10", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
thiserror = "2.0.18"
async-trait = "0.1"
tokio-util = { version = "0.7", features = ["rt"] }
jsonwebtoken = { version = "10.3", default-features = false, features = ["use_pem", "rust_crypto"] }
hmac = "0.13.0"
sha2 = "0.11.0"
hex = "0.4"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
metrics = "0.24.3"
metrics-exporter-prometheus = "0.18.1"
dotenvy = "0.15"
clap = { version = "4.6.1", features = ["derive"] }
ssh2 = "0.9.5"
rand = "0.8"
argon2 = "0.5"
rpassword = "7.5"
rust_decimal = { version = "1.42.0", features = ["serde"] }
reqwest = { version = "0.11", features = ["json"] }
maxminddb = "0.24"
ipnet = "2.10"
flate2 = "1.0"
[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 16
# НЕ panic="abort": по умолчанию tokio ловит панику отдельной задачи (одного
# запроса) через catch_unwind на границе задачи и превращает её в JoinError —
# остальные соединения продолжают жить. panic="abort" эту изоляцию отключает:
# любая паника где угодно в обработчике одного запроса мгновенно убивает весь
# процесс и рвёт всех подключённых пользователей разом.
strip = true